feat: versão 1.5 - CRM Beta com leads, funis, campanhas e portal do cliente
This commit is contained in:
104
backend/internal/api/middleware/unified_auth.go
Normal file
104
backend/internal/api/middleware/unified_auth.go
Normal file
@@ -0,0 +1,104 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user