test(16.3-04): full Go coverage for tokens, guard, account API and CLI

Pin bouncer Scope serialization, party Activated order, lagoon migration,
compile/overlap/mint/expiry/validation, guard/debounce/resolver,
interactive-only, account token API and CLI on Postgres.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-11 13:32:11 +02:00
parent bdd393c15f
commit 78124ab86f
9 changed files with 1303 additions and 0 deletions

View File

@@ -618,3 +618,94 @@ func TestBackendAdminMetadataColumn(t *testing.T) {
t.Fatalf("re-added metadata = %q, want NULL", *restored)
}
}
func TestBackendAPITokensMigration(t *testing.T) {
db, _ := dedicatedDB(t, "lagoon_api_tokens")
gdb, err := Use(t.Context(), db)
if err != nil {
t.Fatal(err)
}
if err := Migrate(gdb, nil); err != nil {
t.Fatal(err)
}
if !gdb.Migrator().HasTable("backend_api_tokens") {
t.Fatal("backend_api_tokens missing after migrate")
}
// Unique token_hash.
if err := gdb.Exec(`INSERT INTO backend_users (login, email, password, is_activated, created_at, updated_at)
VALUES ('tokuser', 'tokuser@example.test', 'x', TRUE, NOW(), NOW())`).Error; err != nil {
t.Fatal(err)
}
var userID int
if err := gdb.Raw(`SELECT id FROM backend_users WHERE login = 'tokuser'`).Scan(&userID).Error; err != nil {
t.Fatal(err)
}
hash := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
if err := gdb.Exec(`INSERT INTO backend_api_tokens (backend_user_id, name, token_hash, token_hint, scopes, created_at, updated_at)
VALUES (?, 'a', ?, 'abcd', '["*"]', NOW(), NOW())`, userID, hash).Error; err != nil {
t.Fatal(err)
}
dup := gdb.Exec(`INSERT INTO backend_api_tokens (backend_user_id, name, token_hash, token_hint, scopes, created_at, updated_at)
VALUES (?, 'b', ?, 'efgh', '["*"]', NOW(), NOW())`, userID, hash)
if dup.Error == nil {
t.Fatal("duplicate token_hash must fail")
}
// FK cascade on hard user delete; revoked_by SET NULL when revoker deleted.
if err := gdb.Exec(`INSERT INTO backend_users (login, email, password, is_activated, created_at, updated_at)
VALUES ('revoker', 'revoker@example.test', 'x', TRUE, NOW(), NOW())`).Error; err != nil {
t.Fatal(err)
}
var revokerID int
if err := gdb.Raw(`SELECT id FROM backend_users WHERE login = 'revoker'`).Scan(&revokerID).Error; err != nil {
t.Fatal(err)
}
hash2 := "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
if err := gdb.Exec(`INSERT INTO backend_api_tokens (backend_user_id, name, token_hash, token_hint, scopes, revoked_by, created_at, updated_at)
VALUES (?, 'c', ?, 'zzzz', '["*"]', ?, NOW(), NOW())`, userID, hash2, revokerID).Error; err != nil {
t.Fatal(err)
}
if err := gdb.Exec(`DELETE FROM backend_users WHERE id = ?`, revokerID).Error; err != nil {
t.Fatal(err)
}
var revokedBy *int
if err := gdb.Raw(`SELECT revoked_by FROM backend_api_tokens WHERE token_hash = ?`, hash2).Scan(&revokedBy).Error; err != nil {
t.Fatal(err)
}
if revokedBy != nil {
t.Fatalf("revoked_by = %v after revoker delete, want NULL", *revokedBy)
}
if err := gdb.Exec(`DELETE FROM backend_users WHERE id = ?`, userID).Error; err != nil {
t.Fatal(err)
}
var n int64
if err := gdb.Raw(`SELECT COUNT(*) FROM backend_api_tokens`).Scan(&n).Error; err != nil {
t.Fatal(err)
}
if n != 0 {
t.Fatalf("cascade left %d tokens", n)
}
if !gdb.Migrator().HasTable("backend_users") {
t.Fatal("backend_users dropped unexpectedly")
}
m, err := migrator(gdb, "summercms.cabana", BackendAdminMigrations)
if err != nil {
t.Fatal(err)
}
if err := m.RollbackLast(); err != nil {
t.Fatal(err)
}
if gdb.Migrator().HasTable("backend_api_tokens") {
t.Fatal("rollback did not drop backend_api_tokens")
}
if !gdb.Migrator().HasTable("backend_users") {
t.Fatal("rollback dropped backend_users")
}
// Re-migrate the rolled-back tokens migration.
if err := m.Migrate(); err != nil {
t.Fatalf("re-migrate: %v", err)
}
if !gdb.Migrator().HasTable("backend_api_tokens") {
t.Fatal("re-migrate missing backend_api_tokens")
}
}