package store_test import ( "context" "testing" ) func TestAppUserRoleAllowsAdmin(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) u, err := s.CreateUser(ctx, accID, "admin@example.com", "hash", "admin") if err != nil { t.Fatalf("CreateUser mit role=admin: %v", err) } if u.Role != "admin" { t.Fatalf("Role = %q, want admin", u.Role) } } func TestAccountVerifiedDefaultsFalseAndCanBeSet(t *testing.T) { s := openTestStore(t) ctx := context.Background() acc, err := s.CreateAccount(ctx, "Kanzlei Musterfrau") if err != nil { t.Fatalf("CreateAccount: %v", err) } if acc.Verified { t.Fatal("expected a new account to be unverified by default") } updated, err := s.SetAccountVerified(ctx, acc.ID, true) if err != nil { t.Fatalf("SetAccountVerified: %v", err) } if !updated.Verified { t.Fatal("expected the account to be verified after SetAccountVerified(true)") } got, err := s.GetAccount(ctx, acc.ID) if err != nil { t.Fatalf("GetAccount: %v", err) } if !got.Verified { t.Fatal("expected verified=true to persist") } } func TestSetAccountVerifiedNotFound(t *testing.T) { s := openTestStore(t) _, err := s.SetAccountVerified(context.Background(), "00000000-0000-0000-0000-000000000000", true) if err == nil { t.Fatal("expected an error for an unknown account") } } func TestListAccounts(t *testing.T) { s := openTestStore(t) ctx := context.Background() before, err := s.ListAccounts(ctx) if err != nil { t.Fatalf("ListAccounts: %v", err) } acc, err := s.CreateAccount(ctx, "Neuer Mandant fuer ListAccounts") if err != nil { t.Fatalf("CreateAccount: %v", err) } after, err := s.ListAccounts(ctx) if err != nil { t.Fatalf("ListAccounts: %v", err) } if len(after) != len(before)+1 { t.Fatalf("expected exactly one more account, got %d -> %d", len(before), len(after)) } found := false for _, a := range after { if a.ID == acc.ID { found = true } } if !found { t.Fatal("expected the newly created account in ListAccounts") } } func TestListVerifiedKanzleienRequiresBothVerifiedAndKanzleiRole(t *testing.T) { s := openTestStore(t) ctx := context.Background() // Verifiziert, aber kein Kanzlei-Nutzer -> darf nicht auftauchen. verifiedNonKanzlei, err := s.CreateAccount(ctx, "Verifizierte Marke") if err != nil { t.Fatalf("CreateAccount: %v", err) } if _, err := s.CreateUser(ctx, verifiedNonKanzlei.ID, "marke@example.com", "hash", "marke"); err != nil { t.Fatalf("CreateUser: %v", err) } if _, err := s.SetAccountVerified(ctx, verifiedNonKanzlei.ID, true); err != nil { t.Fatalf("SetAccountVerified: %v", err) } // Kanzlei-Nutzer, aber nicht verifiziert -> darf nicht auftauchen. unverifiedKanzlei, err := s.CreateAccount(ctx, "Unverifizierte Kanzlei") if err != nil { t.Fatalf("CreateAccount: %v", err) } if _, err := s.CreateUser(ctx, unverifiedKanzlei.ID, "unverifiziert@example.com", "hash", "kanzlei"); err != nil { t.Fatalf("CreateUser: %v", err) } // Beides erfuellt -> muss auftauchen. verifiedKanzlei, err := s.CreateAccount(ctx, "Verifizierte Kanzlei") if err != nil { t.Fatalf("CreateAccount: %v", err) } if _, err := s.CreateUser(ctx, verifiedKanzlei.ID, "verifiziert@example.com", "hash", "kanzlei"); err != nil { t.Fatalf("CreateUser: %v", err) } if _, err := s.SetAccountVerified(ctx, verifiedKanzlei.ID, true); err != nil { t.Fatalf("SetAccountVerified: %v", err) } list, err := s.ListVerifiedKanzleien(ctx) if err != nil { t.Fatalf("ListVerifiedKanzleien: %v", err) } byID := map[string]bool{} for _, a := range list { byID[a.ID] = true } if byID[verifiedNonKanzlei.ID] { t.Error("verified non-kanzlei account should not appear in the directory") } if byID[unverifiedKanzlei.ID] { t.Error("unverified kanzlei account should not appear in the directory") } if !byID[verifiedKanzlei.ID] { t.Error("expected the verified kanzlei account in the directory") } } func TestListUsersForAccount(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) otherAccID := testAccountID(t, s) if _, err := s.CreateUser(ctx, accID, "eins@example.com", "hash", "creator"); err != nil { t.Fatalf("CreateUser: %v", err) } if _, err := s.CreateUser(ctx, accID, "zwei@example.com", "hash", "agentur"); err != nil { t.Fatalf("CreateUser: %v", err) } if _, err := s.CreateUser(ctx, otherAccID, "fremd@example.com", "hash", "marke"); err != nil { t.Fatalf("CreateUser: %v", err) } list, err := s.ListUsersForAccount(ctx, accID) if err != nil { t.Fatalf("ListUsersForAccount: %v", err) } if len(list) != 2 { t.Fatalf("expected exactly 2 users for this account, got %d: %+v", len(list), list) } } func TestAuditLogCreateAndList(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) admin, err := s.CreateUser(ctx, accID, "admin-audit@example.com", "hash", "admin") if err != nil { t.Fatalf("CreateUser: %v", err) } entry, err := s.CreateAuditEntry(ctx, admin.ID, "account.verified", "account", accID, "manuell freigegeben") if err != nil { t.Fatalf("CreateAuditEntry: %v", err) } if entry.ActorUserID != admin.ID { t.Fatalf("ActorUserID = %q, want %q", entry.ActorUserID, admin.ID) } list, err := s.ListAuditLog(ctx, 10) if err != nil { t.Fatalf("ListAuditLog: %v", err) } if len(list) == 0 { t.Fatal("expected at least one audit entry") } if list[0].ID != entry.ID { t.Fatalf("expected the newest entry first, got %+v", list[0]) } } func TestAuditLogIsAppendOnly(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) admin, err := s.CreateUser(ctx, accID, "admin-appendonly@example.com", "hash", "admin") if err != nil { t.Fatalf("CreateUser: %v", err) } entry, err := s.CreateAuditEntry(ctx, admin.ID, "account.verified", "account", accID, "") if err != nil { t.Fatalf("CreateAuditEntry: %v", err) } _, err = s.Pool.Exec(ctx, `UPDATE audit_log SET action = 'geaendert' WHERE id = $1`, entry.ID) if err == nil { t.Fatal("expected UPDATE on audit_log to be rejected by the append-only trigger") } _, err = s.Pool.Exec(ctx, `DELETE FROM audit_log WHERE id = $1`, entry.ID) if err == nil { t.Fatal("expected DELETE on audit_log to be rejected by the append-only trigger") } }