package api import ( "encoding/json" "net/http" "dance-lessons-coach/pkg/user" "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" ) // AuthHandler handles authentication-related HTTP requests type AuthHandler struct { authService user.AuthService } // NewAuthHandler creates a new authentication handler func NewAuthHandler(authService user.AuthService) *AuthHandler { return &AuthHandler{ authService: authService, } } // RegisterRoutes registers authentication routes func (h *AuthHandler) RegisterRoutes(router chi.Router) { router.Post("/login", h.handleLogin) router.Post("/admin/login", h.handleAdminLogin) } // LoginRequest represents a login request type LoginRequest struct { Username string `json:"username" validate:"required,min=3,max=50"` Password string `json:"password" validate:"required,min=6"` } // LoginResponse represents a login response type LoginResponse struct { Token string `json:"token"` } // handleLogin handles user login requests func (h *AuthHandler) handleLogin(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var req LoginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, `{"error":"invalid_request","message":"Invalid JSON request body"}`, http.StatusBadRequest) return } // Authenticate user user, err := h.authService.Authenticate(ctx, req.Username, req.Password) if err != nil { log.Trace().Ctx(ctx).Err(err).Str("username", req.Username).Msg("Authentication failed") http.Error(w, `{"error":"invalid_credentials","message":"Invalid username or password"}`, http.StatusUnauthorized) return } // Generate JWT token token, err := h.authService.GenerateJWT(ctx, user) if err != nil { log.Error().Ctx(ctx).Err(err).Msg("Failed to generate JWT token") http.Error(w, `{"error":"server_error","message":"Failed to generate authentication token"}`, http.StatusInternalServerError) return } // Return token w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(LoginResponse{Token: token}) } // handleAdminLogin handles admin login requests func (h *AuthHandler) handleAdminLogin(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var req LoginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, `{"error":"invalid_request","message":"Invalid JSON request body"}`, http.StatusBadRequest) return } // Authenticate admin adminUser, err := h.authService.AdminAuthenticate(ctx, req.Password) if err != nil { log.Trace().Ctx(ctx).Err(err).Msg("Admin authentication failed") http.Error(w, `{"error":"invalid_credentials","message":"Invalid admin credentials"}`, http.StatusUnauthorized) return } // Generate JWT token token, err := h.authService.GenerateJWT(ctx, adminUser) if err != nil { log.Error().Ctx(ctx).Err(err).Msg("Failed to generate JWT token for admin") http.Error(w, `{"error":"server_error","message":"Failed to generate authentication token"}`, http.StatusInternalServerError) return } // Return token w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(LoginResponse{Token: token}) }