151 lines
4.4 KiB
Go

package handler
import (
"net/http"
"strings"
"time"
"zee/internal/service"
"zee/internal/transport/http/dto"
"github.com/gin-gonic/gin"
)
type AuthHandler struct {
authSvc service.AuthService
}
// NewAuthHandler tạo mới AuthHandler
func NewAuthHandler(authSvc service.AuthService) *AuthHandler {
return &AuthHandler{
authSvc: authSvc,
}
}
// Register xử lý đăng ký người dùng mới
// @Summary Đăng ký tài khoản mới
// @Description Tạo tài khoản người dùng mới với thông tin cơ bản
// @Tags Authentication
// @Accept json
// @Produce json
// @Param request body dto.RegisterRequest true "Thông tin đăng ký"
// @Success 201 {object} dto.UserResponse
// @Failure 400 {object} dto.ErrorResponse
// @Failure 409 {object} dto.ErrorResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /api/v1/auth/register [post]
func (h *AuthHandler) Register(c *gin.Context) {
var req dto.RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, dto.ErrorResponse{Error: "Invalid request body"})
return
}
// Gọi service để đăng ký
user, err := h.authSvc.Register(c.Request.Context(), service.RegisterRequest(req))
if err != nil {
// Xử lý lỗi trả về
if strings.Contains(err.Error(), "already exists") {
c.JSON(http.StatusConflict, dto.ErrorResponse{Error: err.Error()})
} else {
c.JSON(http.StatusInternalServerError, dto.ErrorResponse{Error: "Internal server error"})
}
return
}
// Chuyển đổi sang DTO và trả về
userResponse := dto.ToUserResponse(user)
c.JSON(http.StatusCreated, userResponse)
}
// Login xử lý đăng nhập
// @Summary Đăng nhập
// @Description Đăng nhập bằng username và password
// @Tags Authentication
// @Accept json
// @Produce json
// @Param request body dto.LoginRequest true "Thông tin đăng nhập"
// @Success 200 {object} dto.AuthResponse
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /api/v1/auth/login [post]
func (h *AuthHandler) Login(c *gin.Context) {
var req dto.LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, dto.ErrorResponse{Error: "Invalid request body"})
return
}
// Gọi service để đăng nhập
accessToken, refreshToken, err := h.authSvc.Login(c.Request.Context(), req.Username, req.Password)
if err != nil {
c.JSON(http.StatusUnauthorized, dto.ErrorResponse{Error: "Invalid credentials"})
return
}
// Tạo response
expiresAt := time.Now().Add(24 * time.Hour) // Thời gian hết hạn mặc định
response := dto.AuthResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresAt: expiresAt,
TokenType: "Bearer",
}
c.JSON(http.StatusOK, response)
}
// RefreshToken làm mới access token
// @Summary Làm mới access token
// @Description Làm mới access token bằng refresh token
// @Tags Authentication
// @Accept json
// @Produce json
// @Param refresh_token body string true "Refresh token"
// @Success 200 {object} dto.AuthResponse
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Router /api/v1/auth/refresh [post]
func (h *AuthHandler) RefreshToken(c *gin.Context) {
// Lấy refresh token từ body
var req struct {
RefreshToken string `json:"refresh_token" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, dto.ErrorResponse{Error: "Refresh token is required"})
return
}
// Gọi service để làm mới token
accessToken, refreshToken, err := h.authSvc.RefreshToken(req.RefreshToken)
if err != nil {
c.JSON(http.StatusUnauthorized, dto.ErrorResponse{Error: "Invalid refresh token"})
return
}
// Tạo response
expiresAt := time.Now().Add(24 * time.Hour) // Thời gian hết hạn mặc định
response := dto.AuthResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresAt: expiresAt,
TokenType: "Bearer",
}
c.JSON(http.StatusOK, response)
}
// Logout xử lý đăng xuất
// @Summary Đăng xuất
// @Description Đăng xuất và vô hiệu hóa refresh token
// @Tags Authentication
// @Security Bearer
// @Success 204 "No Content"
// @Router /api/v1/auth/logout [post]
func (h *AuthHandler) Logout(c *gin.Context) {
// TODO: Vô hiệu hóa refresh token trong database
c.Status(http.StatusNoContent)
}