init
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/logger"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
authService service.AuthService
|
||||
}
|
||||
|
||||
func NewAuthHandler(authService service.AuthService) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Login(c *gin.Context) {
|
||||
var req contract.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Login -> request binding failed")
|
||||
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(req.Email) == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Login -> email is required")
|
||||
h.sendValidationErrorResponse(c, "Email is required", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(req.Password) == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Login -> password is required")
|
||||
h.sendValidationErrorResponse(c, "Password is required", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
loginResponse, err := h.authService.Login(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Login -> Failed to login")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::Login -> Successfully logged in user = %s", loginResponse.User.Email)
|
||||
c.JSON(http.StatusOK, loginResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Logout -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.authService.Logout(c.Request.Context(), token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Logout -> Failed to logout")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Info("AuthHandler::Logout -> Successfully logged out")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("Successfully logged out", nil))
|
||||
}
|
||||
|
||||
func (h *AuthHandler) RefreshToken(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::RefreshToken -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
loginResponse, err := h.authService.RefreshToken(c.Request.Context(), token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::RefreshToken -> Failed to refresh token")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::RefreshToken -> Successfully refreshed token for user = %s", loginResponse.User.Email)
|
||||
c.JSON(http.StatusOK, loginResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ValidateToken(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::ValidateToken -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.authService.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::ValidateToken -> Failed to validate token")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::ValidateToken -> Successfully validated token for user = %s", userResponse.Email)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) GetProfile(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::GetProfile -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.authService.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::GetProfile -> Failed to get profile")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::GetProfile -> Successfully retrieved profile for user = %s", userResponse.Email)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
func (h *AuthHandler) extractTokenFromHeader(c *gin.Context) string {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Expected format: "Bearer <token>"
|
||||
parts := strings.Split(authHeader, " ")
|
||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||
return ""
|
||||
}
|
||||
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func (h *AuthHandler) sendErrorResponse(c *gin.Context, message string, statusCode int) {
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: "error",
|
||||
Message: message,
|
||||
Code: statusCode,
|
||||
}
|
||||
c.JSON(statusCode, errorResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) sendValidationErrorResponse(c *gin.Context, message string, errorCode string) {
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: "validation_error",
|
||||
Message: message,
|
||||
Code: http.StatusBadRequest,
|
||||
Details: map[string]interface{}{
|
||||
"error_code": errorCode,
|
||||
"entity": constants.AuthHandlerEntity,
|
||||
},
|
||||
}
|
||||
c.JSON(http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
Reference in New Issue
Block a user