package middleware import ( "go-backend-template/internal/appcontext" "net/http" "strings" "go-backend-template/internal/constants" "go-backend-template/internal/contract" "go-backend-template/internal/logger" "github.com/gin-gonic/gin" ) type AuthMiddleware struct { authService AuthValidateService } func NewAuthMiddleware(authService AuthValidateService) *AuthMiddleware { return &AuthMiddleware{ authService: authService, } } func (m *AuthMiddleware) RequireRole(allowedRoles ...string) gin.HandlerFunc { return func(c *gin.Context) { appCtx := appcontext.FromGinContext(c.Request.Context()) hasRequiredRole := false for _, role := range allowedRoles { if appCtx.UserRole == role { hasRequiredRole = true break } } if !hasRequiredRole { m.sendErrorResponse(c, "Insufficient permissions", http.StatusForbidden) c.Abort() return } c.Next() } } func (m *AuthMiddleware) RequireAdminOrManager() gin.HandlerFunc { return m.RequireRole("admin", "manager") } func (m *AuthMiddleware) RequireAdmin() gin.HandlerFunc { return m.RequireRole("admin") } func (m *AuthMiddleware) RequireSuperAdmin() gin.HandlerFunc { return m.RequireRole("superadmin") } func (m *AuthMiddleware) RequireActiveUser() gin.HandlerFunc { return func(c *gin.Context) { userResponse, exists := c.Get("user") if !exists { logger.FromContext(c.Request.Context()).Error("AuthMiddleware::RequireActiveUser -> User not authenticated") m.sendErrorResponse(c, "Authentication required", http.StatusUnauthorized) c.Abort() return } user, ok := userResponse.(*contract.UserResponse) if !ok { logger.FromContext(c.Request.Context()).Error("AuthMiddleware::RequireActiveUser -> Invalid user context") m.sendErrorResponse(c, "Invalid user context", http.StatusInternalServerError) c.Abort() return } if !user.IsActive { logger.FromContext(c.Request.Context()).Errorf("AuthMiddleware::RequireActiveUser -> User account is deactivated: %s", user.Email) m.sendErrorResponse(c, "User account is deactivated", http.StatusForbidden) c.Abort() return } logger.FromContext(c.Request.Context()).Infof("AuthMiddleware::RequireActiveUser -> Active user check passed: %s", user.Email) c.Next() } } func (m *AuthMiddleware) RequirePermissions(required ...string) gin.HandlerFunc { return func(c *gin.Context) { if _, exists := c.Get("user_permissions"); !exists { m.sendErrorResponse(c, "Authentication required", http.StatusUnauthorized) c.Abort() return } permIface, _ := c.Get("user_permissions") perms, _ := permIface.([]string) userPerms := map[string]bool{} for _, code := range perms { userPerms[code] = true } for _, need := range required { if !userPerms[need] { m.sendErrorResponse(c, "Insufficient permissions", http.StatusForbidden) c.Abort() return } } c.Next() } } func (m *AuthMiddleware) extractTokenFromHeader(c *gin.Context) string { authHeader := c.GetHeader("Authorization") if authHeader == "" { return "" } parts := strings.Split(authHeader, " ") if len(parts) != 2 || parts[0] != "Bearer" { return "" } return parts[1] } func (m *AuthMiddleware) sendErrorResponse(c *gin.Context, message string, statusCode int) { errorResponse := &contract.ErrorResponse{ Error: "auth_error", Message: message, Code: statusCode, Details: map[string]interface{}{ "entity": constants.AuthHandlerEntity, }, } c.JSON(statusCode, errorResponse) }