package service import ( "context" "testing" "time" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" "github.com/gochat/gochat/internal/auth" "github.com/gochat/gochat/internal/config" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/pkg/crypto" ) func setupAuthServiceTest(t *testing.T) (*AuthService, *gorm.DB, *model.User) { t.Helper() db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) require.NoError(t, err) require.NoError(t, db.AutoMigrate(&model.Account{}, &model.User{}, &model.AccountUser{})) account := &model.Account{Name: "Auth Service", Status: "active"} require.NoError(t, db.Create(account).Error) passwordDigest, err := crypto.HashPassword("oldpassword") require.NoError(t, err) user := &model.User{AccountID: account.ID, Name: "Auth User", Email: "auth-service@example.com", Password: passwordDigest, PasswordDigest: passwordDigest, Provider: "email", Active: true} require.NoError(t, db.Create(user).Error) require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "administrator"}).Error) jwtCfg := &config.JWTConfig{Secret: "auth-service-secret", ExpiryHours: 1, RefreshExpiryHours: 24} return NewAuthService(db, auth.NewJWTService(jwtCfg), auth.NewRefreshTokenStore(nil, jwtCfg), nil, nil), db, user } func TestAuthService_ResetPasswordStoresDigestToken(t *testing.T) { svc, db, user := setupAuthServiceTest(t) require.NoError(t, svc.ResetPassword(context.Background(), &ResetPasswordInput{Email: " AUTH-SERVICE@example.com "})) var updated model.User require.NoError(t, db.First(&updated, user.ID).Error) require.NotEmpty(t, updated.ResetPasswordToken) require.NotEqual(t, updated.ResetPasswordToken, "AUTH-SERVICE@example.com") require.NotNil(t, updated.ResetPasswordSentAt) } func TestAuthService_ConfirmResetPasswordUpdatesPasswordAndIssuesTokens(t *testing.T) { svc, db, user := setupAuthServiceTest(t) rawToken := "reset-token-123" sentAt := time.Now().UTC() require.NoError(t, db.Model(user).Updates(map[string]interface{}{ "reset_password_token": digestAuthToken(rawToken), "reset_password_sent_at": sentAt, }).Error) output, err := svc.ConfirmResetPassword(context.Background(), &ConfirmResetPasswordInput{Token: rawToken, Password: "newpassword", PasswordConfirmation: "newpassword"}) require.NoError(t, err) require.NotEmpty(t, output.TokenPair.AccessToken) var updated model.User require.NoError(t, db.First(&updated, user.ID).Error) require.True(t, crypto.CheckPassword("newpassword", updated.PasswordDigest)) require.Empty(t, updated.ResetPasswordToken) require.Nil(t, updated.ResetPasswordSentAt) require.NotNil(t, updated.ConfirmedAt) } func TestAuthService_ConfirmEmailConfirmsAndIssuesTokens(t *testing.T) { svc, db, user := setupAuthServiceTest(t) require.NoError(t, db.Model(user).Updates(map[string]interface{}{ "confirmation_token": "confirm-token-123", "confirmed_at": nil, }).Error) output, err := svc.ConfirmEmail(context.Background(), &ConfirmEmailInput{Token: "confirm-token-123"}) require.NoError(t, err) require.NotEmpty(t, output.TokenPair.AccessToken) var updated model.User require.NoError(t, db.First(&updated, user.ID).Error) require.NotNil(t, updated.ConfirmedAt) require.Empty(t, updated.ConfirmationToken) }