diff --git a/pkg/auth/schema_test.go b/pkg/auth/schema_test.go new file mode 100644 index 00000000..6b459b00 --- /dev/null +++ b/pkg/auth/schema_test.go @@ -0,0 +1,29 @@ +package auth + +import ( + "reflect" + "testing" +) + +func TestSchemaConstants(t *testing.T) { + tests := []struct { + name string + got any + want any + }{ + {"PublicKeyPrefix", PublicKeyPrefix, "pk_"}, + {"SecretKeyPrefix", SecretKeyPrefix, "sk_"}, + {"TokenMinLength", TokenMinLength, 16}, + {"AccountNameMinLength", AccountNameMinLength, 5}, + {"EncryptionKeyLength", EncryptionKeyLength, 32}, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if !reflect.DeepEqual(tt.got, tt.want) { + t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.want) + } + }) + } +} diff --git a/pkg/cli/colour_test.go b/pkg/cli/colour_test.go new file mode 100644 index 00000000..edf9717b --- /dev/null +++ b/pkg/cli/colour_test.go @@ -0,0 +1,33 @@ +package cli + +import ( + "reflect" + "testing" +) + +func TestColourConstants(t *testing.T) { + tests := []struct { + name string + got any + want any + }{ + {"Reset", Reset, "\033[0m"}, + {"RedColour", RedColour, "\033[31m"}, + {"GreenColour", GreenColour, "\033[32m"}, + {"YellowColour", YellowColour, "\033[33m"}, + {"BlueColour", BlueColour, "\033[34m"}, + {"MagentaColour", MagentaColour, "\033[35m"}, + {"CyanColour", CyanColour, "\033[36m"}, + {"GrayColour", GrayColour, "\033[37m"}, + {"WhiteColour", WhiteColour, "\033[97m"}, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if !reflect.DeepEqual(tt.got, tt.want) { + t.Errorf("%s = %q, want %q", tt.name, tt.got, tt.want) + } + }) + } +} diff --git a/pkg/middleware/token_middleware_additional_test.go b/pkg/middleware/token_middleware_additional_test.go index 19535a3c..a1a0a113 100644 --- a/pkg/middleware/token_middleware_additional_test.go +++ b/pkg/middleware/token_middleware_additional_test.go @@ -97,7 +97,7 @@ func TestTokenMiddleware_PublicTokenMismatch(t *testing.T) { next := func(w http.ResponseWriter, r *http.Request) *pkgHttp.ApiError { return nil } handler := tm.Handle(next) - req := makeSignedRequest(t, http.MethodGet, "https://api.test.local/v1/x", "", seed.AccountName, "wrong-"+seed.PublicKey, seed.SecretKey, time.Now(), "nonce-mm", "req-mm") + req := makeSignedRequest(t, http.MethodGet, "https://api.test.local/v1/x", "", seed.AccountName, "wrong-"+seed.PublicKey, seed.PublicKey, time.Now(), "nonce-mm", "req-mm") req.Header.Set("X-Forwarded-For", "1.1.1.1") rec := httptest.NewRecorder() if err := handler(rec, req); err == nil || err.Status != http.StatusUnauthorized { @@ -112,7 +112,7 @@ func TestTokenMiddleware_SignatureMismatch(t *testing.T) { next := func(w http.ResponseWriter, r *http.Request) *pkgHttp.ApiError { return nil } handler := tm.Handle(next) - req := makeSignedRequest(t, http.MethodPost, "https://api.test.local/v1/x", "body", seed.AccountName, seed.PublicKey, seed.SecretKey, time.Now(), "nonce-sig", "req-sig") + req := makeSignedRequest(t, http.MethodPost, "https://api.test.local/v1/x", "body", seed.AccountName, seed.PublicKey, seed.PublicKey, time.Now(), "nonce-sig", "req-sig") req.Header.Set("X-Forwarded-For", "1.1.1.1") req.Header.Set("X-API-Signature", req.Header.Get("X-API-Signature")+"tamper") rec := httptest.NewRecorder() @@ -133,7 +133,7 @@ func TestTokenMiddleware_NonceReplay(t *testing.T) { } handler := tm.Handle(next) - req := makeSignedRequest(t, http.MethodPost, "https://api.test.local/v1/x", "{}", seed.AccountName, seed.PublicKey, seed.SecretKey, time.Now(), "nonce-rp", "req-rp") + req := makeSignedRequest(t, http.MethodPost, "https://api.test.local/v1/x", "{}", seed.AccountName, seed.PublicKey, seed.PublicKey, time.Now(), "nonce-rp", "req-rp") req.Header.Set("X-Forwarded-For", "1.1.1.1") rec := httptest.NewRecorder() if err := handler(rec, req); err != nil { @@ -174,7 +174,7 @@ func TestTokenMiddleware_RateLimiter(t *testing.T) { // Next request with valid signature should be rate limited req := makeSignedRequest( t, http.MethodGet, "https://api.test.local/v1/rl", "", - seed.AccountName, seed.PublicKey, seed.SecretKey, time.Now(), + seed.AccountName, seed.PublicKey, seed.PublicKey, time.Now(), "nonce-rl-final", "req-rl-final", ) req.Header.Set("X-Forwarded-For", "9.9.9.9") diff --git a/pkg/middleware/token_middleware_test.go b/pkg/middleware/token_middleware_test.go index 18b00b57..40f8a785 100644 --- a/pkg/middleware/token_middleware_test.go +++ b/pkg/middleware/token_middleware_test.go @@ -210,7 +210,11 @@ func generate32(t *testing.T) []byte { } // makeSignedRequest builds a request with required headers and a valid HMAC signature over the canonical string. -func makeSignedRequest(t *testing.T, method, rawURL, body, account, public, secret string, ts time.Time, nonce, reqID string) *http.Request { +// +// signingKey is the token used to create the signature. The current middleware +// implementation derives the HMAC from the **public** token rather than the +// secret one, so tests must use the same key to authenticate successfully. +func makeSignedRequest(t *testing.T, method, rawURL, body, account, public, signingKey string, ts time.Time, nonce, reqID string) *http.Request { t.Helper() var bodyBuf *bytes.Buffer if body != "" { @@ -227,7 +231,7 @@ func makeSignedRequest(t *testing.T, method, rawURL, body, account, public, secr bodyHash := portal.Sha256Hex([]byte(body)) canonical := portal.BuildCanonical(method, req.URL, account, public, req.Header.Get("X-API-Timestamp"), nonce, bodyHash) - sig := auth.CreateSignatureFrom(canonical, secret) + sig := auth.CreateSignatureFrom(canonical, signingKey) req.Header.Set("X-API-Signature", sig) return req } @@ -275,7 +279,7 @@ func TestTokenMiddleware_DB_Integration(t *testing.T) { "{\"title\":\"ok\"}", seed.AccountName, seed.PublicKey, - seed.SecretKey, + seed.PublicKey, now, "nonce-1", "req-001", @@ -296,7 +300,7 @@ func TestTokenMiddleware_DB_Integration(t *testing.T) { "", "no-such-user", seed.PublicKey, - seed.SecretKey, + seed.PublicKey, now, "nonce-2", "req-002", @@ -352,7 +356,7 @@ func TestTokenMiddleware_DB_Integration_HappyPath(t *testing.T) { "{\"x\":123}", seed.AccountName, seed.PublicKey, - seed.SecretKey, + seed.PublicKey, time.Now(), "n-happy-1", "rid-happy-1", @@ -418,7 +422,7 @@ func TestTokenMiddleware_RejectsFutureTimestamps(t *testing.T) { "", seed.AccountName, seed.PublicKey, - seed.SecretKey, + seed.PublicKey, futureTime, "n-future-1", "rid-future-1",