package handlers import ( "api-service/internal/models/auth" models "api-service/internal/models/auth" services "api-service/internal/services/auth" "net/http" "github.com/gin-gonic/gin" ) // AuthHandler handles authentication endpoints type AuthHandler struct { authService *services.AuthService } // NewAuthHandler creates a new authentication handler func NewAuthHandler(authService *services.AuthService) *AuthHandler { return &AuthHandler{ authService: authService, } } // Login godoc // @Summary Login user and get JWT token // @Description Authenticate user with username and password to receive JWT token // @Tags Authentication // @Accept json // @Produce json // @Param login body models.LoginRequest true "Login credentials" // @Success 200 {object} models.TokenResponse // @Failure 400 {object} map[string]string "Bad request" // @Failure 401 {object} map[string]string "Unauthorized" // @Router /api/v1/auth/login [post] func (h *AuthHandler) Login(c *gin.Context) { var loginReq models.LoginRequest // Bind JSON request if err := c.ShouldBindJSON(&loginReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Authenticate user tokenResponse, err := h.authService.Login(loginReq.Username, loginReq.Password) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tokenResponse) } // RefreshToken godoc // @Summary Refresh JWT token // @Description Refresh the JWT token using a valid refresh token // @Tags Authentication // @Accept json // @Produce json // @Param refresh body map[string]string true "Refresh token" // @Success 200 {object} models.TokenResponse // @Failure 400 {object} map[string]string "Bad request" // @Failure 401 {object} map[string]string "Unauthorized" // @Router /api/v1/auth/refresh [post] func (h *AuthHandler) RefreshToken(c *gin.Context) { var refreshReq auth.RefreshTokenRequest // Bind JSON request if err := c.ShouldBindJSON(&refreshReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Refresh token tokenResponse, err := h.authService.RefreshToken(refreshReq.RefreshToken) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tokenResponse) } // Register godoc // @Summary Register new user // @Description Register a new user account // @Tags Authentication // @Accept json // @Produce json // @Param register body map[string]string true "Registration data" // @Success 201 {object} map[string]string // @Failure 400 {object} map[string]string "Bad request" // @Router /api/v1/auth/register [post] func (h *AuthHandler) Register(c *gin.Context) { var registerReq auth.RegisterRequest if err := c.ShouldBindJSON(®isterReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } err := h.authService.RegisterUser( registerReq.Username, registerReq.Email, registerReq.Password, registerReq.Role, ) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"message": "user registered successfully"}) } // Me godoc // @Summary Get current user info // @Description Get information about the currently authenticated user // @Tags Authentication // @Produce json // @Security Bearer // @Success 200 {object} models.User // @Failure 401 {object} map[string]string "Unauthorized" // @Router /api/v1/auth/me [get] func (h *AuthHandler) Me(c *gin.Context) { // Get user info from context (set by middleware) userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"}) return } // In a real implementation, you would fetch user details from database c.JSON(http.StatusOK, auth.UserResponse{ ID: userID.(string), Username: c.GetString("username"), Email: c.GetString("email"), Role: c.GetString("role"), }) } // TokenHandler handles token generation endpoints type TokenHandler struct { authService *services.AuthService } // NewTokenHandler creates a new token handler func NewTokenHandler(authService *services.AuthService) *TokenHandler { return &TokenHandler{ authService: authService, } } // GenerateToken godoc // @Summary Generate JWT token // @Description Generate a JWT token for testing purposes // @Tags Token // @Accept json // @Produce json // @Param token body map[string]interface{} true "Token generation data" // @Success 200 {object} models.TokenResponse // @Failure 400 {object} map[string]string "Bad request" // @Router /api/v1/token/generate [post] func (h *TokenHandler) GenerateToken(c *gin.Context) { var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Extract user data from request userID, ok := req["user_id"].(string) if !ok || userID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "user_id is required"}) return } username, _ := req["username"].(string) email, _ := req["email"].(string) role, _ := req["role"].(string) // Generate token tokenResponse, err := h.authService.GenerateToken(userID, username, email, role) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tokenResponse) } // GenerateTokenDirect godoc // @Summary Generate JWT token directly // @Description Generate a JWT token directly with provided data // @Tags Token // @Accept json // @Produce json // @Param token body map[string]interface{} true "Token generation data" // @Success 200 {object} models.TokenResponse // @Failure 400 {object} map[string]string "Bad request" // @Router /api/v1/token/generate-direct [post] func (h *TokenHandler) GenerateTokenDirect(c *gin.Context) { var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Extract user data from request userID, ok := req["user_id"].(string) if !ok || userID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "user_id is required"}) return } username, _ := req["username"].(string) email, _ := req["email"].(string) role, _ := req["role"].(string) // Generate token directly tokenResponse, err := h.authService.GenerateTokenDirect(userID, username, email, role) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tokenResponse) }