summaryrefslogtreecommitdiff
path: root/player-server/internal/repository/api_token_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-17 21:21:42 +0300
committerPaul Buetow <paul@buetow.org>2026-05-17 21:21:42 +0300
commita7fbe6d5008decde1e2402b422300d83d3a3de0e (patch)
tree9e4a23c260e417aa34a894c117f3ff4351b68753 /player-server/internal/repository/api_token_test.go
parent27562eaf12a112d46986a4e8ec3dfcc342ae4738 (diff)
Add api_tokens table, model, and repository
Diffstat (limited to 'player-server/internal/repository/api_token_test.go')
-rw-r--r--player-server/internal/repository/api_token_test.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/player-server/internal/repository/api_token_test.go b/player-server/internal/repository/api_token_test.go
new file mode 100644
index 0000000..fe1e923
--- /dev/null
+++ b/player-server/internal/repository/api_token_test.go
@@ -0,0 +1,139 @@
+package repository
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "codeberg.org/snonux/player/internal/model"
+)
+
+func TestSQLite_APITokenRepo(t *testing.T) {
+ ctx := context.Background()
+ s := newTestStore(t)
+ defer s.Close()
+
+ now := time.Date(2026, 5, 17, 12, 0, 0, 0, time.UTC)
+ userID := mustCreateAPITokenUser(t, ctx, s, "api-user")
+ otherUserID := mustCreateAPITokenUser(t, ctx, s, "other-api-user")
+
+ expiresAt := now.Add(24 * time.Hour)
+ firstID, err := s.Create(ctx, &model.APIToken{
+ UserID: userID,
+ TokenHash: "hash-one",
+ Name: "first token",
+ ExpiresAt: &expiresAt,
+ CreatedAt: now,
+ })
+ if err != nil {
+ t.Fatalf("create first token: %v", err)
+ }
+
+ got, err := s.GetByHash(ctx, "hash-one")
+ if err != nil {
+ t.Fatalf("get by hash: %v", err)
+ }
+ if got == nil {
+ t.Fatal("expected token, got nil")
+ }
+ assertAPIToken(t, got, firstID, userID, "hash-one", "first token", nil, &expiresAt, now)
+
+ lastUsedAt := now.Add(time.Hour)
+ secondID, err := s.Create(ctx, &model.APIToken{
+ UserID: userID,
+ TokenHash: "hash-two",
+ Name: "second token",
+ LastUsedAt: &lastUsedAt,
+ CreatedAt: now.Add(time.Minute),
+ })
+ if err != nil {
+ t.Fatalf("create second token: %v", err)
+ }
+ if _, err := s.Create(ctx, &model.APIToken{
+ UserID: otherUserID,
+ TokenHash: "hash-other",
+ Name: "other token",
+ CreatedAt: now.Add(2 * time.Minute),
+ }); err != nil {
+ t.Fatalf("create other user token: %v", err)
+ }
+
+ tokens, err := s.ListByUser(ctx, userID)
+ if err != nil {
+ t.Fatalf("list by user: %v", err)
+ }
+ if len(tokens) != 2 {
+ t.Fatalf("expected 2 tokens, got %d", len(tokens))
+ }
+ if tokens[0].ID != secondID || tokens[1].ID != firstID {
+ t.Fatalf("unexpected list order: %+v", tokens)
+ }
+
+ touchedAt := now.Add(2 * time.Hour)
+ if err := s.TouchLastUsed(ctx, firstID, touchedAt); err != nil {
+ t.Fatalf("touch last used: %v", err)
+ }
+ got, err = s.GetByHash(ctx, "hash-one")
+ if err != nil {
+ t.Fatalf("get touched token: %v", err)
+ }
+ assertTimePtr(t, got.LastUsedAt, &touchedAt, "last used after touch")
+
+ if err := s.DeleteByID(ctx, firstID); err != nil {
+ t.Fatalf("delete by id: %v", err)
+ }
+ got, err = s.GetByHash(ctx, "hash-one")
+ if err != nil {
+ t.Fatalf("get deleted token: %v", err)
+ }
+ if got != nil {
+ t.Fatalf("expected deleted token to be nil, got %+v", got)
+ }
+}
+
+func mustCreateAPITokenUser(t *testing.T, ctx context.Context, s *SQLite, username string) int64 {
+ t.Helper()
+ id, err := s.CreateUser(ctx, &model.User{
+ Username: username,
+ PasswordHash: "hash",
+ CreatedAt: time.Date(2026, 5, 17, 11, 0, 0, 0, time.UTC),
+ })
+ if err != nil {
+ t.Fatalf("create user %q: %v", username, err)
+ }
+ return id
+}
+
+func assertAPIToken(t *testing.T, token *model.APIToken, id, userID int64, tokenHash, name string, lastUsedAt, expiresAt *time.Time, createdAt time.Time) {
+ t.Helper()
+ if token.ID != id {
+ t.Fatalf("expected id %d, got %d", id, token.ID)
+ }
+ if token.UserID != userID {
+ t.Fatalf("expected user id %d, got %d", userID, token.UserID)
+ }
+ if token.TokenHash != tokenHash {
+ t.Fatalf("expected token hash %q, got %q", tokenHash, token.TokenHash)
+ }
+ if token.Name != name {
+ t.Fatalf("expected name %q, got %q", name, token.Name)
+ }
+ assertTimePtr(t, token.LastUsedAt, lastUsedAt, "last used")
+ assertTimePtr(t, token.ExpiresAt, expiresAt, "expires")
+ if !token.CreatedAt.Equal(createdAt) {
+ t.Fatalf("expected created at %s, got %s", createdAt, token.CreatedAt)
+ }
+}
+
+func assertTimePtr(t *testing.T, got, want *time.Time, field string) {
+ t.Helper()
+ if got == nil || want == nil {
+ if got != want {
+ t.Fatalf("expected %s %v, got %v", field, want, got)
+ }
+ return
+ }
+ if !got.Equal(*want) {
+ t.Fatalf("expected %s %s, got %s", field, *want, *got)
+ }
+}