turash/bugulma/backend/internal/middleware/auth.go

111 lines
2.9 KiB
Go

package middleware
import (
"fmt"
"net/http"
"strings"
"bugulma/backend/internal/service"
"github.com/gin-gonic/gin"
)
func AuthMiddleware(authService *service.AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"})
c.Abort()
return
}
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if tokenString == authHeader {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid authorization format"})
c.Abort()
return
}
user, err := authService.ValidateToken(c.Request.Context(), tokenString)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
c.Abort()
return
}
// Set user information in context
c.Set("user_id", user.ID)
c.Set("user_email", user.Email)
c.Set("user_role", string(user.Role))
// Debug: Log the role being set (only in development)
if gin.Mode() == gin.DebugMode {
fmt.Printf("[AuthMiddleware] Setting user_role=%s for user_id=%s\n", string(user.Role), user.ID)
}
c.Next()
}
}
func RequireRole(role string) gin.HandlerFunc {
return func(c *gin.Context) {
// Debug: Log all context keys (only in development)
if gin.Mode() == gin.DebugMode {
fmt.Printf("[RequireRole] Checking for role=%s, path=%s\n", role, c.Request.URL.Path)
// Try to get all context values for debugging
if userID, exists := c.Get("user_id"); exists {
fmt.Printf("[RequireRole] Found user_id=%v\n", userID)
}
if userEmail, exists := c.Get("user_email"); exists {
fmt.Printf("[RequireRole] Found user_email=%v\n", userEmail)
}
}
userRole, exists := c.Get("user_role")
if !exists {
// Debug: List all available keys in context
if gin.Mode() == gin.DebugMode {
fmt.Printf("[RequireRole] user_role not found. Available keys in context:\n")
// Note: Gin doesn't provide a direct way to list all keys, but we can check common ones
}
c.JSON(http.StatusForbidden, gin.H{
"error": "No role found - authentication middleware may not be applied",
"required_role": role,
"path": c.Request.URL.Path,
})
c.Abort()
return
}
// Convert to string for comparison - handle both string and interface{} types
var userRoleStr string
switch v := userRole.(type) {
case string:
userRoleStr = v
default:
userRoleStr = fmt.Sprintf("%v", v)
}
// Trim whitespace and compare (case-sensitive)
userRoleStr = strings.TrimSpace(userRoleStr)
if userRoleStr != role {
c.JSON(http.StatusForbidden, gin.H{
"error": "Insufficient permissions",
"required_role": role,
"user_role": userRoleStr,
"debug": map[string]interface{}{
"user_role_type": fmt.Sprintf("%T", userRole),
"user_role_raw": userRole,
"user_role_string": userRoleStr,
"required_role": role,
"match": userRoleStr == role,
},
})
c.Abort()
return
}
c.Next()
}
}