Files
aura-crm/production/backend/internal/license/license_test.go
T
root 56ffca767d feat: offline license/trial system
7-day full-access trial, then gated behind an Ed25519-signed license key
(internal/license) verified entirely offline — no phone-home dependency.
Middleware 402s non-exempt API routes once the trial lapses with no valid
key; frontend shows a countdown banner in the last 3 days and a blocking
overlay once actually gated, both pointing at the new Settings -> Лицензия
tab. tools/gen-license mints keys for the vendor side (never ships the
private key).
2026-08-21 18:44:54 +00:00

64 lines
1.8 KiB
Go

package license
import (
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"testing"
"time"
)
// testKeyPair generates a fresh Ed25519 pair and signs payload with the
// resulting private key — Parse itself always verifies against the
// package's real embedded publicKeyHex, so these helpers exist only to
// exercise the malformed/tampered paths that don't need a genuine
// signature to fail correctly.
func signWithKey(priv ed25519.PrivateKey, p Payload) string {
payloadJSON, _ := json.Marshal(p)
payloadB64 := base64.RawURLEncoding.EncodeToString(payloadJSON)
sig := ed25519.Sign(priv, []byte(payloadB64))
sigB64 := base64.RawURLEncoding.EncodeToString(sig)
return payloadB64 + "." + sigB64
}
func TestParseRejectsSignatureFromWrongKey(t *testing.T) {
_, wrongPriv, _ := ed25519.GenerateKey(nil)
key := signWithKey(wrongPriv, Payload{Customer: "Someone"})
_, err := Parse(key)
if err != ErrInvalidSignature {
t.Errorf("Parse() err = %v, want ErrInvalidSignature", err)
}
}
func TestParseRejectsMalformedInput(t *testing.T) {
cases := []string{"", "no-dot-here", "not-base64.also-not-base64", "..", "a.b.c"}
for _, c := range cases {
if _, err := Parse(c); err == nil {
t.Errorf("Parse(%q) = nil error, want an error", c)
}
}
}
func TestPayloadValidPerpetualNeverExpires(t *testing.T) {
p := Payload{Customer: "X", IssuedAt: time.Now()}
if !p.Valid() {
t.Error("Valid() = false for a nil-ExpiresAt (perpetual) payload, want true")
}
}
func TestPayloadValidRespectsExpiry(t *testing.T) {
past := time.Now().Add(-time.Hour)
future := time.Now().Add(time.Hour)
expired := Payload{ExpiresAt: &past}
if expired.Valid() {
t.Error("Valid() = true for an already-expired payload, want false")
}
current := Payload{ExpiresAt: &future}
if !current.Valid() {
t.Error("Valid() = false for a not-yet-expired payload, want true")
}
}