105 lines
3.5 KiB
Go
105 lines
3.5 KiB
Go
package middleware
|
|
|
|
import (
|
|
"aggios-app/backend/internal/config"
|
|
"aggios-app/backend/internal/domain"
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
)
|
|
|
|
// UnifiedAuthMiddleware valida JWT unificado e permite múltiplos tipos de usuários
|
|
func UnifiedAuthMiddleware(cfg *config.Config, allowedTypes ...domain.UserType) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Extrair token do header Authorization
|
|
authHeader := r.Header.Get("Authorization")
|
|
if authHeader == "" {
|
|
log.Printf("🚫 UnifiedAuth: Missing Authorization header")
|
|
http.Error(w, "Unauthorized: Missing token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Formato esperado: "Bearer <token>"
|
|
parts := strings.Split(authHeader, " ")
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
log.Printf("🚫 UnifiedAuth: Invalid Authorization format")
|
|
http.Error(w, "Unauthorized: Invalid token format", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
tokenString := parts[1]
|
|
|
|
// Parsear e validar token
|
|
token, err := jwt.ParseWithClaims(tokenString, &domain.UnifiedClaims{}, func(token *jwt.Token) (interface{}, error) {
|
|
return []byte(cfg.JWT.Secret), nil
|
|
})
|
|
|
|
if err != nil {
|
|
log.Printf("🚫 UnifiedAuth: Token parse error: %v", err)
|
|
http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
claims, ok := token.Claims.(*domain.UnifiedClaims)
|
|
if !ok || !token.Valid {
|
|
log.Printf("🚫 UnifiedAuth: Invalid token claims")
|
|
http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Verificar se o tipo de usuário é permitido
|
|
if len(allowedTypes) > 0 {
|
|
allowed := false
|
|
for _, allowedType := range allowedTypes {
|
|
if claims.UserType == allowedType {
|
|
allowed = true
|
|
break
|
|
}
|
|
}
|
|
if !allowed {
|
|
log.Printf("🚫 UnifiedAuth: User type %s not allowed (allowed: %v)", claims.UserType, allowedTypes)
|
|
http.Error(w, "Forbidden: Insufficient permissions", http.StatusForbidden)
|
|
return
|
|
}
|
|
}
|
|
|
|
// Adicionar informações ao contexto
|
|
ctx := r.Context()
|
|
ctx = context.WithValue(ctx, UserIDKey, claims.UserID)
|
|
ctx = context.WithValue(ctx, TenantIDKey, claims.TenantID)
|
|
ctx = context.WithValue(ctx, "email", claims.Email)
|
|
ctx = context.WithValue(ctx, "user_type", string(claims.UserType))
|
|
ctx = context.WithValue(ctx, "role", claims.Role)
|
|
|
|
// Para compatibilidade com handlers de portal que esperam CustomerIDKey
|
|
if claims.UserType == domain.UserTypeCustomer {
|
|
ctx = context.WithValue(ctx, CustomerIDKey, claims.UserID)
|
|
}
|
|
|
|
log.Printf("✅ UnifiedAuth: Authenticated user_id=%s, type=%s, role=%s, tenant=%s",
|
|
claims.UserID, claims.UserType, claims.Role, claims.TenantID)
|
|
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
}
|
|
|
|
// RequireAgencyUser middleware que permite apenas usuários de agência (admin, colaborador)
|
|
func RequireAgencyUser(cfg *config.Config) func(http.Handler) http.Handler {
|
|
return UnifiedAuthMiddleware(cfg, domain.UserTypeAgency)
|
|
}
|
|
|
|
// RequireCustomer middleware que permite apenas clientes
|
|
func RequireCustomer(cfg *config.Config) func(http.Handler) http.Handler {
|
|
return UnifiedAuthMiddleware(cfg, domain.UserTypeCustomer)
|
|
}
|
|
|
|
// RequireAnyAuthenticated middleware que permite qualquer usuário autenticado
|
|
func RequireAnyAuthenticated(cfg *config.Config) func(http.Handler) http.Handler {
|
|
return UnifiedAuthMiddleware(cfg) // Sem filtro de tipo
|
|
}
|