From 9b8d0b2b3e11beaf6e47d02edf02d87dbb2a7231 Mon Sep 17 00:00:00 2001 From: Andrej Mickov Date: Mon, 2 Mar 2026 23:39:39 +0100 Subject: [PATCH] add auth service tests for user admin primitives --- auth/service_admin_test.go | 137 +++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 auth/service_admin_test.go diff --git a/auth/service_admin_test.go b/auth/service_admin_test.go new file mode 100644 index 0000000..c190e11 --- /dev/null +++ b/auth/service_admin_test.go @@ -0,0 +1,137 @@ +package auth + +import ( + "encoding/base64" + "errors" + "fs/metadata" + "fs/models" + "path/filepath" + "testing" +) + +func TestAdminCreateListGetUser(t *testing.T) { + meta, svc := newTestAuthService(t) + + created, err := svc.CreateUser(CreateUserInput{ + AccessKeyID: "backup-user", + Policy: models.AuthPolicy{ + Statements: []models.AuthPolicyStatement{ + { + Effect: "allow", + Actions: []string{"s3:GetObject"}, + Bucket: "backup-bucket", + Prefix: "restic/", + }, + }, + }, + }) + if err != nil { + t.Fatalf("CreateUser returned error: %v", err) + } + if created.SecretKey == "" { + t.Fatalf("CreateUser should return generated secret") + } + if created.AccessKeyID != "backup-user" { + t.Fatalf("CreateUser access key mismatch: got %q", created.AccessKeyID) + } + if created.Policy.Principal != "backup-user" { + t.Fatalf("policy principal mismatch: got %q", created.Policy.Principal) + } + + users, nextCursor, err := svc.ListUsers(100, "") + if err != nil { + t.Fatalf("ListUsers returned error: %v", err) + } + if nextCursor != "" { + t.Fatalf("unexpected next cursor: %q", nextCursor) + } + if len(users) != 1 { + t.Fatalf("ListUsers returned %d users, want 1", len(users)) + } + if users[0].AccessKeyID != "backup-user" { + t.Fatalf("ListUsers returned wrong user: %q", users[0].AccessKeyID) + } + + got, err := svc.GetUser("backup-user") + if err != nil { + t.Fatalf("GetUser returned error: %v", err) + } + if got.AccessKeyID != "backup-user" { + t.Fatalf("GetUser access key mismatch: got %q", got.AccessKeyID) + } + if got.Policy.Principal != "backup-user" { + t.Fatalf("GetUser policy principal mismatch: got %q", got.Policy.Principal) + } + if len(got.Policy.Statements) != 1 { + t.Fatalf("GetUser policy statement count = %d, want 1", len(got.Policy.Statements)) + } + + _ = meta +} + +func TestCreateUserDuplicateFails(t *testing.T) { + _, svc := newTestAuthService(t) + + input := CreateUserInput{ + AccessKeyID: "duplicate-user", + SecretKey: "super-secret-1", + Policy: models.AuthPolicy{ + Statements: []models.AuthPolicyStatement{ + {Effect: "allow", Actions: []string{"s3:*"}, Bucket: "*", Prefix: "*"}, + }, + }, + } + if _, err := svc.CreateUser(input); err != nil { + t.Fatalf("first CreateUser returned error: %v", err) + } + if _, err := svc.CreateUser(input); !errors.Is(err, ErrUserAlreadyExists) { + t.Fatalf("second CreateUser error = %v, want ErrUserAlreadyExists", err) + } +} + +func TestCreateUserRejectsInvalidAccessKey(t *testing.T) { + _, svc := newTestAuthService(t) + + _, err := svc.CreateUser(CreateUserInput{ + AccessKeyID: "x", + SecretKey: "super-secret-1", + Policy: models.AuthPolicy{ + Statements: []models.AuthPolicyStatement{ + {Effect: "allow", Actions: []string{"s3:*"}, Bucket: "*", Prefix: "*"}, + }, + }, + }) + if !errors.Is(err, ErrInvalidUserInput) { + t.Fatalf("CreateUser error = %v, want ErrInvalidUserInput", err) + } +} + +func newTestAuthService(t *testing.T) (*metadata.MetadataHandler, *Service) { + t.Helper() + + dbPath := filepath.Join(t.TempDir(), "metadata.db") + meta, err := metadata.NewMetadataHandler(dbPath) + if err != nil { + t.Fatalf("NewMetadataHandler returned error: %v", err) + } + t.Cleanup(func() { + _ = meta.Close() + }) + + masterKey := base64.StdEncoding.EncodeToString(make([]byte, 32)) + cfg := ConfigFromValues( + true, + "us-east-1", + 0, + 0, + masterKey, + "root-user", + "root-secret-123", + "", + ) + svc, err := NewService(cfg, meta) + if err != nil { + t.Fatalf("NewService returned error: %v", err) + } + return meta, svc +}