f2c534f636
- mongo-driver v2 connection with bounded startup retry + /readyz gate - idempotent creation of all §4.9 indexes - UpdateVersioned: version-filtered updates, conflict vs not-found errors - AES-256-GCM Seal/Open for ticketing credentials, base64(nonce|ct) - GridFS file store: MIME sniffing, MAX_UPLOAD_MB cap, sha256 metadata - HMAC-signed short-lived file URL tokens (§5.1, 1h TTL) - integration tests against compose Mongo via docker-compose.test.yml overlay Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package files
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSignVerifyRoundTrip(t *testing.T) {
|
|
secret := []byte("0123456789abcdef0123456789abcdef")
|
|
now := time.Now()
|
|
token := SignToken(secret, "01JFILE", now.Add(time.Hour))
|
|
|
|
if !VerifyToken(secret, "01JFILE", token, now) {
|
|
t.Fatal("fresh token must verify")
|
|
}
|
|
if !VerifyToken(secret, "01JFILE", token, now.Add(59*time.Minute)) {
|
|
t.Fatal("token must verify just before expiry")
|
|
}
|
|
}
|
|
|
|
func TestVerifyRejections(t *testing.T) {
|
|
secret := []byte("0123456789abcdef0123456789abcdef")
|
|
now := time.Now()
|
|
token := SignToken(secret, "01JFILE", now.Add(time.Hour))
|
|
|
|
tests := []struct {
|
|
name string
|
|
fileID string
|
|
token string
|
|
at time.Time
|
|
}{
|
|
{"expired", "01JFILE", token, now.Add(2 * time.Hour)},
|
|
{"wrong file", "01JOTHER", token, now},
|
|
{"garbage token", "01JFILE", "not-a-token", now},
|
|
{"empty token", "01JFILE", "", now},
|
|
{"truncated token", "01JFILE", token[:len(token)-10], now},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if VerifyToken(secret, tt.fileID, tt.token, tt.at) {
|
|
t.Error("must not verify")
|
|
}
|
|
})
|
|
}
|
|
|
|
if VerifyToken([]byte("another-secret-another-secret-xx"), "01JFILE", token, now) {
|
|
t.Error("different secret must not verify")
|
|
}
|
|
}
|
|
|
|
func TestSignedURLShape(t *testing.T) {
|
|
secret := []byte("0123456789abcdef0123456789abcdef")
|
|
u := SignedURL("http://localhost:8787", secret, "01JFILE", time.Now().Add(time.Hour))
|
|
if !strings.HasPrefix(u, "http://localhost:8787/files/01JFILE?st=") {
|
|
t.Fatalf("unexpected URL %q", u)
|
|
}
|
|
token := u[strings.Index(u, "?st=")+4:]
|
|
if !VerifyToken(secret, "01JFILE", token, time.Now()) {
|
|
t.Fatal("token embedded in URL must verify")
|
|
}
|
|
}
|