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:
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user