Item 1.4 — Register no longer issues an access+refresh token pair. The
prior flow set httpOnly cookies at register but the AuthMiddleware
refused them on every protected route until the user had verified
their email (`core/auth/service.go:527`). Users ended up with dead
credentials and a "logged in but locked out" UX. Register now returns
{user, verification_required: true, message} and the SPA's existing
"check your email" notice fires naturally.
Item 1.3 — `POST /auth/verify-email` reads the token from the
`X-Verify-Token` header in preference to the `?token=…` query param.
Query param logged a deprecation warning but stays accepted so emails
dispatched before this release still work. Headers don't leak through
proxy/CDN access logs that record URL but not headers.
Tests: 18 test files updated (sed `_, _, err :=` → `_, err :=` for the
new Register signature). `core/auth/handler_test.go` gets a
`registerVerifyLogin` helper for tests that exercise post-login flows
(refresh, logout). Two new E2E `@critical` specs lock in the defer-JWT
contract and the header read-path.
OpenAPI + orval regenerated to reflect the new RegisterResponse shape
and the verify-email header parameter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
599 lines
18 KiB
Go
599 lines
18 KiB
Go
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"veza-backend-api/internal/config"
|
|
"veza-backend-api/internal/core/auth"
|
|
"veza-backend-api/internal/database"
|
|
"veza-backend-api/internal/dto"
|
|
"veza-backend-api/internal/models"
|
|
"veza-backend-api/internal/repositories"
|
|
"veza-backend-api/internal/services"
|
|
"veza-backend-api/internal/validators"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zaptest"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// setupAuthTestRouter creates a test router with real auth service and mocked dependencies.
|
|
// Optional authMiddlewares are applied to the /auth group before routes (for tests needing user_id in context).
|
|
func setupAuthTestRouter(t *testing.T, authMiddlewares ...gin.HandlerFunc) (*gin.Engine, *auth.AuthService, *services.SessionService, *services.TwoFactorService, *services.UserService, *zap.Logger, func(), *gorm.DB) {
|
|
gin.SetMode(gin.TestMode)
|
|
logger := zaptest.NewLogger(t)
|
|
|
|
// Setup in-memory database
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
// Enable foreign keys for SQLite
|
|
db.Exec("PRAGMA foreign_keys = ON")
|
|
|
|
// Auto-migrate models
|
|
err = db.AutoMigrate(
|
|
&models.User{},
|
|
&models.RefreshToken{},
|
|
&models.Session{},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Create email_verification_tokens table manually (no GORM model)
|
|
err = db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS email_verification_tokens (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token TEXT NOT NULL UNIQUE,
|
|
token_hash TEXT NOT NULL,
|
|
email TEXT NOT NULL,
|
|
verified INTEGER NOT NULL DEFAULT 0,
|
|
used INTEGER NOT NULL DEFAULT 0,
|
|
verified_at TIMESTAMP,
|
|
expires_at TIMESTAMP NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
`).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create database wrapper
|
|
dbWrapper := &database.Database{}
|
|
dbWrapper.GormDB = db
|
|
|
|
// Get underlying SQL DB for services that need it (like EmailVerificationService)
|
|
sqlDB, err := db.DB()
|
|
require.NoError(t, err)
|
|
dbWrapper.DB = sqlDB
|
|
|
|
// Add 2FA columns to users (SQLite test DB; GORM User model may not have them)
|
|
// Ignore errors if columns already exist (e.g. from a future GORM migration)
|
|
_, _ = sqlDB.Exec("ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN DEFAULT 0")
|
|
_, _ = sqlDB.Exec("ALTER TABLE users ADD COLUMN two_factor_secret TEXT DEFAULT ''")
|
|
_, _ = sqlDB.Exec("ALTER TABLE users ADD COLUMN backup_codes TEXT DEFAULT '[]'")
|
|
|
|
// Setup services
|
|
emailValidator := validators.NewEmailValidator(db)
|
|
passwordValidator := validators.NewPasswordValidator()
|
|
passwordService := services.NewPasswordService(dbWrapper, logger)
|
|
jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
|
|
require.NoError(t, err)
|
|
refreshTokenService := services.NewRefreshTokenService(db)
|
|
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
|
|
passwordResetService := services.NewPasswordResetService(dbWrapper, logger)
|
|
emailService := services.NewEmailService(dbWrapper, logger)
|
|
|
|
// Create AuthService
|
|
authService := auth.NewAuthService(
|
|
db,
|
|
emailValidator,
|
|
passwordValidator,
|
|
passwordService,
|
|
jwtService,
|
|
refreshTokenService,
|
|
emailVerificationService,
|
|
passwordResetService,
|
|
emailService,
|
|
nil, // jobWorker - not needed for unit tests
|
|
nil, // refreshLock - not needed for unit tests
|
|
logger,
|
|
)
|
|
|
|
// Create other services
|
|
sessionService := services.NewSessionService(dbWrapper, logger)
|
|
twoFactorService := services.NewTwoFactorService(dbWrapper, logger)
|
|
|
|
// Create UserService with GORM repository
|
|
userRepo := repositories.NewGormUserRepository(db)
|
|
userService := services.NewUserServiceWithDB(userRepo, db)
|
|
|
|
// Create default config
|
|
cfg := &config.Config{}
|
|
|
|
router := gin.New()
|
|
authGroup := router.Group("/auth")
|
|
for _, mw := range authMiddlewares {
|
|
authGroup.Use(mw)
|
|
}
|
|
{
|
|
authGroup.POST("/login", Login(authService, sessionService, twoFactorService, logger, cfg))
|
|
authGroup.POST("/register", Register(authService, sessionService, logger, cfg))
|
|
authGroup.POST("/refresh", Refresh(authService, sessionService, logger, cfg))
|
|
authGroup.POST("/logout", Logout(authService, sessionService, logger, cfg))
|
|
authGroup.POST("/verify-email", VerifyEmail(authService))
|
|
authGroup.POST("/resend-verification", ResendVerification(authService, logger))
|
|
authGroup.GET("/check-username", CheckUsername(authService))
|
|
authGroup.GET("/me", GetMe(userService))
|
|
}
|
|
|
|
cleanup := func() {
|
|
// Database cleanup handled by test
|
|
}
|
|
|
|
return router, authService, sessionService, twoFactorService, userService, logger, cleanup, db
|
|
}
|
|
|
|
func TestLogin_Success(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, db := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a test user first
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, user)
|
|
|
|
// Verify email to allow login
|
|
db.Model(&models.User{}).Where("id = ?", user.ID).Update("is_verified", true)
|
|
|
|
reqBody := dto.LoginRequest{
|
|
Email: "test@example.com",
|
|
Password: "SecurePassword123!",
|
|
RememberMe: false,
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/login", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response APIResponse
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.True(t, response.Success)
|
|
}
|
|
|
|
func TestLogin_InvalidCredentials(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, db := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a test user first
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, user)
|
|
|
|
// Verify email
|
|
db.Model(&models.User{}).Where("id = ?", user.ID).Update("is_verified", true)
|
|
|
|
reqBody := dto.LoginRequest{
|
|
Email: "test@example.com",
|
|
Password: "wrongpassword",
|
|
RememberMe: false,
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/login", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code) // invalid credentials -> 401 (auth.go returns 401)
|
|
}
|
|
|
|
func TestLogin_EmailNotVerified(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a test user but don't verify email
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, user)
|
|
// User is not verified by default (v1.0.4: Register leaves is_verified=false).
|
|
|
|
reqBody := dto.LoginRequest{
|
|
Email: "test@example.com",
|
|
Password: "SecurePassword123!",
|
|
RememberMe: false,
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/login", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
// Login refuses unverified users; the user must POST /auth/verify-email first.
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
}
|
|
|
|
func TestLogin_Requires2FA(t *testing.T) {
|
|
router, authService, _, twoFactorService, _, _, cleanup, db := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a test user
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, user)
|
|
|
|
// Verify email - use GORM directly
|
|
db.Model(&models.User{}).Where("id = ?", user.ID).Update("is_verified", true)
|
|
|
|
// Enable 2FA for user - generate secret and enable
|
|
setup, err := twoFactorService.GenerateSecret(user)
|
|
require.NoError(t, err)
|
|
err = twoFactorService.EnableTwoFactor(ctx, user.ID, setup.Secret, setup.RecoveryCodes)
|
|
require.NoError(t, err)
|
|
|
|
reqBody := dto.LoginRequest{
|
|
Email: "test@example.com",
|
|
Password: "SecurePassword123!",
|
|
RememberMe: false,
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/login", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response APIResponse
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.True(t, response.Success)
|
|
|
|
// Check that response contains requires_2fa flag
|
|
var loginResponse dto.LoginResponse
|
|
responseData, _ := json.Marshal(response.Data)
|
|
json.Unmarshal(responseData, &loginResponse)
|
|
assert.True(t, loginResponse.Requires2FA)
|
|
}
|
|
|
|
func TestLogin_InvalidRequest(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Missing email
|
|
reqBody := map[string]interface{}{
|
|
"password": "password123",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/login", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestRegister_Success(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
reqBody := dto.RegisterRequest{
|
|
Email: "newuser@example.com",
|
|
Username: "newuser",
|
|
Password: "SecurePassword123!",
|
|
PasswordConfirm: "SecurePassword123!",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/register", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusCreated, w.Code)
|
|
var response APIResponse
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.True(t, response.Success)
|
|
}
|
|
|
|
func TestRegister_UserAlreadyExists(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a user first
|
|
ctx := context.Background()
|
|
_, err := authService.Register(ctx, "existing@example.com", "existinguser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
|
|
// Try to register again with same email
|
|
reqBody := dto.RegisterRequest{
|
|
Email: "existing@example.com",
|
|
Username: "existinguser2",
|
|
Password: "SecurePassword123!",
|
|
PasswordConfirm: "SecurePassword123!",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/register", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusConflict, w.Code)
|
|
}
|
|
|
|
func TestRegister_InvalidEmail(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Invalid email format will be caught by validation
|
|
reqBody := dto.RegisterRequest{
|
|
Email: "invalid-email",
|
|
Username: "newuser",
|
|
Password: "SecurePassword123!",
|
|
PasswordConfirm: "SecurePassword123!",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/register", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
// Should fail validation before reaching service
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestRegister_WeakPassword(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Weak password will be caught by validation (min=12)
|
|
reqBody := dto.RegisterRequest{
|
|
Email: "newuser@example.com",
|
|
Username: "newuser",
|
|
Password: "weak",
|
|
PasswordConfirm: "weak",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/register", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
// Should fail validation before reaching service
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestRegister_InvalidRequest(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Missing required fields
|
|
reqBody := map[string]interface{}{
|
|
"email": "test@example.com",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/register", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestRefresh_InvalidRequest(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Missing refresh_token
|
|
reqBody := map[string]interface{}{}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/refresh", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestLogout_Success(t *testing.T) {
|
|
userID := uuid.New()
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t, func(c *gin.Context) {
|
|
if c.Request.URL.Path == "/auth/logout" {
|
|
c.Set("user_id", userID)
|
|
}
|
|
c.Next()
|
|
})
|
|
defer cleanup()
|
|
|
|
reqBody := map[string]interface{}{
|
|
"refresh_token": "refresh_token",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/logout", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer access_token")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestLogout_Unauthorized(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
reqBody := map[string]interface{}{
|
|
"refresh_token": "refresh_token",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/logout", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
|
}
|
|
|
|
func TestVerifyEmail_MissingToken(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/verify-email", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestResendVerification_Success(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, db := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a test user (not verified) - Register creates with is_verified=true by default, so we set false
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
db.Model(&models.User{}).Where("id = ?", user.ID).Update("is_verified", false)
|
|
|
|
reqBody := dto.ResendVerificationRequest{
|
|
Email: "test@example.com",
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req := httptest.NewRequest(http.MethodPost, "/auth/resend-verification", bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestCheckUsername_Available(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/auth/check-username?username=newusername", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response APIResponse
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.True(t, response.Success)
|
|
|
|
var data map[string]interface{}
|
|
responseData, _ := json.Marshal(response.Data)
|
|
json.Unmarshal(responseData, &data)
|
|
assert.True(t, data["available"].(bool))
|
|
}
|
|
|
|
func TestCheckUsername_Taken(t *testing.T) {
|
|
router, authService, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Create a user with username
|
|
ctx := context.Background()
|
|
_, err := authService.Register(ctx, "test@example.com", "existinguser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/auth/check-username?username=existinguser", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var response APIResponse
|
|
json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.True(t, response.Success)
|
|
|
|
var data map[string]interface{}
|
|
responseData, _ := json.Marshal(response.Data)
|
|
json.Unmarshal(responseData, &data)
|
|
assert.False(t, data["available"].(bool))
|
|
}
|
|
|
|
func TestCheckUsername_MissingUsername(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/auth/check-username", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestGetMe_Success(t *testing.T) {
|
|
var userID uuid.UUID
|
|
router, authService, _, _, _, _, cleanup, _ := setupAuthTestRouter(t, func(c *gin.Context) {
|
|
if c.Request.URL.Path == "/auth/me" {
|
|
c.Set("user_id", userID)
|
|
}
|
|
c.Next()
|
|
})
|
|
defer cleanup()
|
|
|
|
// Create a test user
|
|
ctx := context.Background()
|
|
user, err := authService.Register(ctx, "test@example.com", "testuser", "SecurePassword123!")
|
|
require.NoError(t, err)
|
|
userID = user.ID
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/auth/me", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestGetMe_Unauthorized(t *testing.T) {
|
|
router, _, _, _, _, _, cleanup, _ := setupAuthTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/auth/me", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
|
}
|