Files
2025-10-31 02:30:27 +00:00

230 lines
6.4 KiB
Go

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(&registerReq); 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)
}