151 lines
4.4 KiB
Go
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)
|
|
}
|