package store_test import ( "context" "errors" "testing" "time" "github.com/netcell-it/deklarix/internal/store" ) func TestAccountCRUD(t *testing.T) { s := openTestStore(t) ctx := context.Background() acc, err := s.CreateAccount(ctx, "Beispiel Agentur GmbH") if err != nil { t.Fatalf("CreateAccount: %v", err) } got, err := s.GetAccount(ctx, acc.ID) if err != nil { t.Fatalf("GetAccount: %v", err) } if got.Name != "Beispiel Agentur GmbH" { t.Fatalf("Name = %q, want Beispiel Agentur GmbH", got.Name) } if got.EinladungToken == "" { t.Error("expected a newly created account to have a non-empty EinladungToken") } } func TestGetAccountByEinladungToken(t *testing.T) { s := openTestStore(t) ctx := context.Background() acc, err := s.CreateAccount(ctx, "Beispiel Agentur GmbH") if err != nil { t.Fatalf("CreateAccount: %v", err) } got, err := s.GetAccountByEinladungToken(ctx, acc.EinladungToken) if err != nil { t.Fatalf("GetAccountByEinladungToken: %v", err) } if got.ID != acc.ID { t.Fatalf("GetAccountByEinladungToken returned a different account") } _, err = s.GetAccountByEinladungToken(ctx, "unbekanntes-token") if !errors.Is(err, store.ErrNotFound) { t.Fatalf("err = %v, want store.ErrNotFound for an unknown token", err) } } func TestRegenerateEinladungToken(t *testing.T) { s := openTestStore(t) ctx := context.Background() acc, err := s.CreateAccount(ctx, "Beispiel Agentur GmbH") if err != nil { t.Fatalf("CreateAccount: %v", err) } alterToken := acc.EinladungToken if err := s.RegenerateEinladungToken(ctx, acc.ID, "ein-neues-token"); err != nil { t.Fatalf("RegenerateEinladungToken: %v", err) } if _, err := s.GetAccountByEinladungToken(ctx, alterToken); !errors.Is(err, store.ErrNotFound) { t.Fatalf("expected the old token to be invalid, got err = %v", err) } got, err := s.GetAccountByEinladungToken(ctx, "ein-neues-token") if err != nil { t.Fatalf("GetAccountByEinladungToken (neu): %v", err) } if got.ID != acc.ID { t.Fatalf("GetAccountByEinladungToken (neu) returned a different account") } } func TestUserCRUD(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) user, err := s.CreateUser(ctx, accID, "team@example.com", "bcrypt-hash", "mitarbeiter") if err != nil { t.Fatalf("CreateUser: %v", err) } byEmail, err := s.GetUserByEmail(ctx, "team@example.com") if err != nil { t.Fatalf("GetUserByEmail: %v", err) } if byEmail.ID != user.ID { t.Fatalf("GetUserByEmail returned a different user than CreateUser") } byID, err := s.GetUser(ctx, user.ID) if err != nil { t.Fatalf("GetUser: %v", err) } if byID.Email != "team@example.com" || byID.AccountID != accID { t.Fatalf("GetUser = %+v, unerwartete Werte", byID) } if !byID.Active { t.Error("expected a newly created user to be Active by default") } } func TestSetUserActive(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) user, err := s.CreateUser(ctx, accID, "deaktivierbar@example.com", "bcrypt-hash", "mitarbeiter") if err != nil { t.Fatalf("CreateUser: %v", err) } if err := s.SetUserActive(ctx, user.ID, false); err != nil { t.Fatalf("SetUserActive (false): %v", err) } deaktiviert, err := s.GetUser(ctx, user.ID) if err != nil { t.Fatalf("GetUser: %v", err) } if deaktiviert.Active { t.Fatal("expected the user to be inactive") } if err := s.SetUserActive(ctx, user.ID, true); err != nil { t.Fatalf("SetUserActive (true): %v", err) } reaktiviert, err := s.GetUser(ctx, user.ID) if err != nil { t.Fatalf("GetUser: %v", err) } if !reaktiviert.Active { t.Fatal("expected the user to be active again") } } func TestSetUserActiveNotFound(t *testing.T) { s := openTestStore(t) err := s.SetUserActive(context.Background(), "00000000-0000-0000-0000-000000000000", false) if !errors.Is(err, store.ErrNotFound) { t.Fatalf("err = %v, want store.ErrNotFound", err) } } func TestGetUserByEmailNotFound(t *testing.T) { s := openTestStore(t) _, err := s.GetUserByEmail(context.Background(), "nichtvorhanden@example.com") if !errors.Is(err, store.ErrNotFound) { t.Fatalf("err = %v, want store.ErrNotFound", err) } } func TestUserEmailIsUnique(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) if _, err := s.CreateUser(ctx, accID, "doppelt@example.com", "hash1", "mitarbeiter"); err != nil { t.Fatalf("CreateUser (1): %v", err) } if _, err := s.CreateUser(ctx, accID, "doppelt@example.com", "hash2", "mitarbeiter"); err == nil { t.Fatal("expected error for a duplicate email, got nil") } } func TestSessionCRUD(t *testing.T) { s := openTestStore(t) ctx := context.Background() accID := testAccountID(t, s) user, err := s.CreateUser(ctx, accID, "session@example.com", "hash", "verantwortlicher") if err != nil { t.Fatalf("CreateUser: %v", err) } expiresAt := time.Now().Add(time.Hour).Truncate(time.Millisecond) sess, err := s.CreateSession(ctx, "test-token-123", user.ID, expiresAt) if err != nil { t.Fatalf("CreateSession: %v", err) } got, err := s.GetSession(ctx, sess.Token) if err != nil { t.Fatalf("GetSession: %v", err) } if got.UserID != user.ID { t.Fatalf("UserID = %q, want %q", got.UserID, user.ID) } if got.ImpersonatedByUserID != nil { t.Errorf("ImpersonatedByUserID = %v, want nil for a regular session", got.ImpersonatedByUserID) } if err := s.DeleteSession(ctx, sess.Token); err != nil { t.Fatalf("DeleteSession: %v", err) } if _, err := s.GetSession(ctx, sess.Token); !errors.Is(err, store.ErrNotFound) { t.Fatalf("err after delete = %v, want store.ErrNotFound", err) } } func TestGetSessionNotFound(t *testing.T) { s := openTestStore(t) _, err := s.GetSession(context.Background(), "unbekanntes-token") if !errors.Is(err, store.ErrNotFound) { t.Fatalf("err = %v, want store.ErrNotFound", err) } } func TestCreateImpersonatedSession(t *testing.T) { s := openTestStore(t) ctx := context.Background() kundenAcc := testAccountID(t, s) kundenNutzer, err := s.CreateUser(ctx, kundenAcc, "kunde@example.com", "hash", "admin") if err != nil { t.Fatalf("CreateUser (Kunde): %v", err) } betreiberAcc := testAccountID(t, s) betreiber, err := s.CreateUser(ctx, betreiberAcc, "betreiber@example.com", "hash", "betreiber") if err != nil { t.Fatalf("CreateUser (Betreiber): %v", err) } expiresAt := time.Now().Add(time.Hour).Truncate(time.Millisecond) sess, err := s.CreateImpersonatedSession(ctx, "support-token-123", kundenNutzer.ID, betreiber.ID, expiresAt) if err != nil { t.Fatalf("CreateImpersonatedSession: %v", err) } if sess.UserID != kundenNutzer.ID { t.Errorf("UserID = %q, want %q", sess.UserID, kundenNutzer.ID) } if sess.ImpersonatedByUserID == nil || *sess.ImpersonatedByUserID != betreiber.ID { t.Fatalf("ImpersonatedByUserID = %v, want %q", sess.ImpersonatedByUserID, betreiber.ID) } got, err := s.GetSession(ctx, sess.Token) if err != nil { t.Fatalf("GetSession: %v", err) } if got.ImpersonatedByUserID == nil || *got.ImpersonatedByUserID != betreiber.ID { t.Fatalf("GetSession ImpersonatedByUserID = %v, want %q", got.ImpersonatedByUserID, betreiber.ID) } }