feat(auth): replace hand-rolled auth with Ory Kratos — phase 2 backend
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Backend CI / Build (push) Has been cancelled

Delegates all credential management (login, register, password reset,
email verification, social sign-in) to Ory Kratos. The Go API now acts
as a resource server: the new KratosAuth middleware validates sessions
against the Kratos whoami endpoint, writes the local User mirror into
Echo context, and all existing domain handlers continue working
unchanged. Hand-rolled token auth, AuthToken model, apple_auth/
google_auth services, and the auth refresh flow are removed. Tests are
updated to use the fake-token middleware pattern so existing integration
assertions require no rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-05-18 17:55:56 -05:00
parent b66151ddd9
commit 81578f6e27
36 changed files with 927 additions and 7002 deletions
+43 -666
View File
@@ -4,7 +4,6 @@ import (
"context"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -19,195 +18,18 @@ func setupAuthService(t *testing.T) (*AuthService, *repositories.UserRepository)
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
notifRepo := repositories.NewNotificationRepository(db)
cfg := &config.Config{
Server: config.ServerConfig{
DebugFixedCodes: true,
},
Security: config.SecurityConfig{
SecretKey: "test-secret",
ConfirmationExpiry: 24 * time.Hour,
PasswordResetExpiry: 15 * time.Minute,
MaxPasswordResetRate: 3,
TokenExpiryDays: 90,
TokenRefreshDays: 60,
},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
service.SetNotificationRepository(notifRepo)
return service, userRepo
}
// === Login ===
func TestAuthService_Login(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
req := &requests.LoginRequest{
Username: "testuser",
Password: "Password123",
}
resp, err := service.Login(context.Background(), req, "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Token)
assert.Equal(t, "testuser", resp.User.Username)
}
func TestAuthService_Login_ByEmail(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
req := &requests.LoginRequest{
Email: "test@test.com",
Password: "Password123",
}
resp, err := service.Login(context.Background(), req, "")
require.NoError(t, err)
assert.NotEmpty(t, resp.Token)
}
func TestAuthService_Login_InvalidCredentials(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
req := &requests.LoginRequest{
Username: "testuser",
Password: "WrongPassword1",
}
_, err := service.Login(context.Background(), req, "")
testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}
func TestAuthService_Login_UserNotFound(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
req := &requests.LoginRequest{
Username: "nonexistent",
Password: "Password123",
}
_, err := service.Login(context.Background(), req, "")
testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}
func TestAuthService_Login_InactiveUser(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "inactive", "inactive@test.com", "Password123")
// Deactivate
user.IsActive = false
db.Save(user)
req := &requests.LoginRequest{
Username: "inactive",
Password: "Password123",
}
_, err := service.Login(context.Background(), req, "")
// Audit L1: inactive accounts return the same generic error as bad
// credentials so login does not disclose which accounts exist.
testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}
// === Register ===
func TestAuthService_Register(t *testing.T) {
service, _ := setupAuthService(t)
req := &requests.RegisterRequest{
Username: "newuser",
Email: "new@test.com",
Password: "Password123",
}
resp, code, err := service.Register(context.Background(), req)
require.NoError(t, err)
assert.NotEmpty(t, resp.Token)
assert.Equal(t, "newuser", resp.User.Username)
assert.Equal(t, "123456", code) // DebugFixedCodes=true
}
func TestAuthService_Register_DuplicateUsername(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Server: config.ServerConfig{DebugFixedCodes: true},
Security: config.SecurityConfig{SecretKey: "test", ConfirmationExpiry: 24 * time.Hour},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "taken", "taken@test.com", "Password123")
req := &requests.RegisterRequest{
Username: "taken",
Email: "different@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
testutil.AssertAppError(t, err, http.StatusConflict, "error.username_taken")
}
func TestAuthService_Register_DuplicateEmail(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Server: config.ServerConfig{DebugFixedCodes: true},
Security: config.SecurityConfig{SecretKey: "test", ConfirmationExpiry: 24 * time.Hour},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "existing", "taken@test.com", "Password123")
req := &requests.RegisterRequest{
Username: "newuser",
Email: "taken@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
testutil.AssertAppError(t, err, http.StatusConflict, "error.email_taken")
}
// === GetCurrentUser ===
func TestAuthService_GetCurrentUser(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
@@ -218,7 +40,7 @@ func TestAuthService_GetCurrentUser(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "testuser", resp.Username)
assert.Equal(t, "test@test.com", resp.Email)
assert.Equal(t, "email", resp.AuthProvider) // Default for no social auth
assert.Equal(t, "kratos", resp.AuthProvider) // All users are Kratos-managed
}
// === UpdateProfile ===
@@ -226,9 +48,7 @@ func TestAuthService_GetCurrentUser(t *testing.T) {
func TestAuthService_UpdateProfile(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
@@ -250,9 +70,7 @@ func TestAuthService_UpdateProfile(t *testing.T) {
func TestAuthService_UpdateProfile_DuplicateEmail(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "user1", "user1@test.com", "Password123")
@@ -271,9 +89,7 @@ func TestAuthService_UpdateProfile_DuplicateEmail(t *testing.T) {
func TestAuthService_UpdateProfile_SameEmail(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
@@ -290,443 +106,10 @@ func TestAuthService_UpdateProfile_SameEmail(t *testing.T) {
assert.Equal(t, "test@test.com", resp.Email)
}
// === VerifyEmail ===
func TestAuthService_VerifyEmail(t *testing.T) {
service, _ := setupAuthService(t)
// Register a user (creates confirmation code)
req := &requests.RegisterRequest{
Username: "newuser",
Email: "new@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
require.NoError(t, err)
// Get the user ID
user, err := service.userRepo.FindByEmail("new@test.com")
require.NoError(t, err)
// Verify with the debug code
err = service.VerifyEmail(context.Background(), user.ID, "123456")
require.NoError(t, err)
// Verify again — should get already verified error
err = service.VerifyEmail(context.Background(), user.ID, "123456")
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.email_already_verified")
}
func TestAuthService_VerifyEmail_InvalidCode(t *testing.T) {
service, _ := setupAuthService(t)
// Register
req := &requests.RegisterRequest{
Username: "newuser",
Email: "new@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("new@test.com")
require.NoError(t, err)
// Wrong code — with DebugFixedCodes enabled, "123456" bypasses normal lookup,
// but a wrong code should use the normal path
err = service.VerifyEmail(context.Background(), user.ID, "000000")
assert.Error(t, err)
}
// === ResendVerificationCode ===
func TestAuthService_ResendVerificationCode(t *testing.T) {
service, _ := setupAuthService(t)
// Register
req := &requests.RegisterRequest{
Username: "newuser",
Email: "new@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("new@test.com")
require.NoError(t, err)
code, err := service.ResendVerificationCode(context.Background(), user.ID)
require.NoError(t, err)
assert.Equal(t, "123456", code) // DebugFixedCodes
}
func TestAuthService_ResendVerificationCode_AlreadyVerified(t *testing.T) {
service, _ := setupAuthService(t)
// Register and verify
req := &requests.RegisterRequest{
Username: "newuser",
Email: "new@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), req)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("new@test.com")
require.NoError(t, err)
err = service.VerifyEmail(context.Background(), user.ID, "123456")
require.NoError(t, err)
_, err = service.ResendVerificationCode(context.Background(), user.ID)
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.email_already_verified")
}
// === ForgotPassword ===
func TestAuthService_ForgotPassword(t *testing.T) {
service, _ := setupAuthService(t)
// Register a user first
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
code, user, err := service.ForgotPassword(context.Background(), "test@test.com")
require.NoError(t, err)
assert.Equal(t, "123456", code) // DebugFixedCodes
assert.NotNil(t, user)
assert.Equal(t, "test@test.com", user.Email)
}
func TestAuthService_ForgotPassword_NonexistentEmail(t *testing.T) {
service, _ := setupAuthService(t)
// Should not reveal that email doesn't exist
code, user, err := service.ForgotPassword(context.Background(), "nonexistent@test.com")
require.NoError(t, err)
assert.Empty(t, code)
assert.Nil(t, user)
}
// === ResetPassword ===
func TestAuthService_ResetPassword(t *testing.T) {
service, _ := setupAuthService(t)
// Register
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
// Forgot password
_, _, err = service.ForgotPassword(context.Background(), "test@test.com")
require.NoError(t, err)
// Verify reset code to get the token
resetToken, err := service.VerifyResetCode(context.Background(), "test@test.com", "123456")
require.NoError(t, err)
assert.NotEmpty(t, resetToken)
// Reset password
err = service.ResetPassword(context.Background(), resetToken, "NewPassword123")
require.NoError(t, err)
// Login with new password
loginReq := &requests.LoginRequest{
Username: "testuser",
Password: "NewPassword123",
}
loginResp, err := service.Login(context.Background(), loginReq, "")
require.NoError(t, err)
assert.NotEmpty(t, loginResp.Token)
}
func TestAuthService_ResetPassword_InvalidToken(t *testing.T) {
service, _ := setupAuthService(t)
err := service.ResetPassword(context.Background(), "invalid-token", "NewPassword123")
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.invalid_reset_token")
}
// === Logout ===
func TestAuthService_Logout(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
// Login first
loginReq := &requests.LoginRequest{
Username: "testuser",
Password: "Password123",
}
loginResp, err := service.Login(context.Background(), loginReq, "")
require.NoError(t, err)
// Logout
err = service.Logout(context.Background(), loginResp.Token)
require.NoError(t, err)
// Token should be deleted — refreshing should fail
_, err = service.RefreshToken(context.Background(), loginResp.Token, user.ID)
assert.Error(t, err)
}
// === DeleteAccount ===
func TestAuthService_DeleteAccount_EmailAuth(t *testing.T) {
service, _ := setupAuthService(t)
// Register
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("test@test.com")
require.NoError(t, err)
password := "Password123"
_, err = service.DeleteAccount(context.Background(), user.ID, &password, nil)
require.NoError(t, err)
}
func TestAuthService_DeleteAccount_WrongPassword(t *testing.T) {
service, _ := setupAuthService(t)
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("test@test.com")
require.NoError(t, err)
wrongPassword := "WrongPassword1"
_, err = service.DeleteAccount(context.Background(), user.ID, &wrongPassword, nil)
testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}
func TestAuthService_DeleteAccount_NoPassword(t *testing.T) {
service, _ := setupAuthService(t)
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("test@test.com")
require.NoError(t, err)
_, err = service.DeleteAccount(context.Background(), user.ID, nil, nil)
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.password_required")
}
func TestAuthService_DeleteAccount_UserNotFound(t *testing.T) {
service, _ := setupAuthService(t)
password := "Password123"
_, err := service.DeleteAccount(context.Background(), 99999, &password, nil)
testutil.AssertAppError(t, err, http.StatusNotFound, "error.user_not_found")
}
// === Helper functions ===
func TestGenerateSixDigitCode(t *testing.T) {
code := generateSixDigitCode()
assert.Len(t, code, 6)
// Should be numeric
for _, c := range code {
assert.True(t, c >= '0' && c <= '9', "code should contain only digits")
}
}
func TestGenerateResetToken(t *testing.T) {
token := generateResetToken()
assert.NotEmpty(t, token)
assert.Len(t, token, 64) // 32 bytes = 64 hex chars
}
func TestGetStringOrEmpty(t *testing.T) {
s := "hello"
assert.Equal(t, "hello", getStringOrEmpty(&s))
assert.Equal(t, "", getStringOrEmpty(nil))
}
func TestIsPrivateRelayEmail(t *testing.T) {
assert.True(t, isPrivateRelayEmail("abc@privaterelay.appleid.com"))
assert.True(t, isPrivateRelayEmail("ABC@PRIVATERELAY.APPLEID.COM"))
assert.False(t, isPrivateRelayEmail("user@gmail.com"))
}
func TestGetEmailFromRequest(t *testing.T) {
email := "req@test.com"
assert.Equal(t, "req@test.com", getEmailFromRequest(&email, "claims@test.com"))
assert.Equal(t, "claims@test.com", getEmailFromRequest(nil, "claims@test.com"))
empty := ""
assert.Equal(t, "claims@test.com", getEmailFromRequest(&empty, "claims@test.com"))
}
// === getEmailOrDefault ===
func TestGetEmailOrDefault(t *testing.T) {
// Non-empty email returns itself
assert.Equal(t, "user@test.com", getEmailOrDefault("user@test.com"))
// Empty email returns a generated placeholder
result := getEmailOrDefault("")
assert.Contains(t, result, "@privaterelay.appleid.com")
assert.Contains(t, result, "apple_")
}
// === generateUniqueUsername ===
func TestGenerateUniqueUsername(t *testing.T) {
// Normal email generates username from email prefix
username := generateUniqueUsername("john@test.com", nil)
assert.Contains(t, username, "john_")
// Private relay email falls back to first name
firstName := "Jane"
username = generateUniqueUsername("abc@privaterelay.appleid.com", &firstName)
assert.Contains(t, username, "jane_")
// Private relay email and no first name — fallback
username = generateUniqueUsername("abc@privaterelay.appleid.com", nil)
assert.Contains(t, username, "user_")
// Empty email with first name
firstName2 := "Bob"
username = generateUniqueUsername("", &firstName2)
assert.Contains(t, username, "bob_")
// Empty email and no first name
username = generateUniqueUsername("", nil)
assert.Contains(t, username, "user_")
}
// === generateGoogleUsername ===
func TestGenerateGoogleUsername(t *testing.T) {
// Normal email
username := generateGoogleUsername("john@gmail.com", "John")
assert.Contains(t, username, "john_")
// Empty email falls back to first name
username = generateGoogleUsername("", "Alice")
assert.Contains(t, username, "alice_")
// Empty email and empty first name — fallback
username = generateGoogleUsername("", "")
assert.Contains(t, username, "google_")
}
// === Login with empty password ===
func TestAuthService_Login_EmptyPassword(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
service := NewAuthService(userRepo, cfg)
testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
req := &requests.LoginRequest{
Username: "testuser",
Password: "",
}
_, err := service.Login(context.Background(), req, "")
testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}
// === ForgotPassword rate limiting ===
func TestAuthService_ForgotPassword_RateLimit(t *testing.T) {
service, _ := setupAuthService(t)
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
// Make max allowed reset requests (3 based on setup)
for i := 0; i < 3; i++ {
_, _, err := service.ForgotPassword(context.Background(), "test@test.com")
require.NoError(t, err)
}
// The 4th should be rate limited
_, _, err = service.ForgotPassword(context.Background(), "test@test.com")
assert.Error(t, err)
}
// === VerifyResetCode with wrong code ===
func TestAuthService_VerifyResetCode_WrongCode(t *testing.T) {
service, _ := setupAuthService(t)
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
_, _, err = service.ForgotPassword(context.Background(), "test@test.com")
require.NoError(t, err)
// Wrong code but with debug mode, "123456" works, "000000" should fail
_, err = service.VerifyResetCode(context.Background(), "test@test.com", "000000")
assert.Error(t, err)
}
// === VerifyResetCode with nonexistent email ===
func TestAuthService_VerifyResetCode_NonexistentEmail(t *testing.T) {
service, _ := setupAuthService(t)
_, err := service.VerifyResetCode(context.Background(), "nonexistent@test.com", "123456")
assert.Error(t, err)
}
// === UpdateProfile — change email to new email ===
func TestAuthService_UpdateProfile_ChangeEmail(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
@@ -742,25 +125,44 @@ func TestAuthService_UpdateProfile_ChangeEmail(t *testing.T) {
assert.Equal(t, "newemail@test.com", resp.Email)
}
// === DeleteAccount — empty password string ===
// === DeleteAccount ===
func TestAuthService_DeleteAccount_EmptyPassword(t *testing.T) {
func TestAuthService_DeleteAccount_WithConfirmation(t *testing.T) {
service, userRepo := setupAuthService(t)
user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "")
_ = user
confirmation := "DELETE"
_, err := service.DeleteAccount(context.Background(), user.ID, nil, &confirmation)
require.NoError(t, err)
}
func TestAuthService_DeleteAccount_WrongConfirmation(t *testing.T) {
service, userRepo := setupAuthService(t)
user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "")
wrongConf := "delete"
_, err := service.DeleteAccount(context.Background(), user.ID, nil, &wrongConf)
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.confirmation_required")
}
func TestAuthService_DeleteAccount_NoConfirmation(t *testing.T) {
service, userRepo := setupAuthService(t)
user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "")
_, err := service.DeleteAccount(context.Background(), user.ID, nil, nil)
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.confirmation_required")
}
func TestAuthService_DeleteAccount_UserNotFound(t *testing.T) {
service, _ := setupAuthService(t)
registerReq := &requests.RegisterRequest{
Username: "testuser",
Email: "test@test.com",
Password: "Password123",
}
_, _, err := service.Register(context.Background(), registerReq)
require.NoError(t, err)
user, err := service.userRepo.FindByEmail("test@test.com")
require.NoError(t, err)
emptyPw := ""
_, err = service.DeleteAccount(context.Background(), user.ID, &emptyPw, nil)
testutil.AssertAppError(t, err, http.StatusBadRequest, "error.password_required")
confirmation := "DELETE"
_, err := service.DeleteAccount(context.Background(), 99999, nil, &confirmation)
testutil.AssertAppError(t, err, http.StatusNotFound, "error.user_not_found")
}
// === SetNotificationRepository ===
@@ -769,35 +171,10 @@ func TestAuthService_SetNotificationRepository(t *testing.T) {
db := testutil.SetupTestDB(t)
userRepo := repositories.NewUserRepository(db)
notifRepo := repositories.NewNotificationRepository(db)
cfg := &config.Config{
Security: config.SecurityConfig{SecretKey: "test-secret"},
}
cfg := &config.Config{}
service := NewAuthService(userRepo, cfg)
assert.Nil(t, service.notificationRepo)
service.SetNotificationRepository(notifRepo)
assert.NotNil(t, service.notificationRepo)
}
// === Register creates profile and notification preferences ===
func TestAuthService_Register_CreatesProfile(t *testing.T) {
service, userRepo := setupAuthService(t)
req := &requests.RegisterRequest{
Username: "profileuser",
Email: "profile@test.com",
Password: "Password123",
FirstName: "John",
LastName: "Doe",
}
resp, _, err := service.Register(context.Background(), req)
require.NoError(t, err)
assert.Equal(t, "profileuser", resp.User.Username)
// Profile should exist
profile, err := userRepo.GetOrCreateProfile(resp.User.ID)
require.NoError(t, err)
assert.NotNil(t, profile)
}