v1.4: Segurança multi-tenant, file serving via API e UX humanizada
- Validação cross-tenant no login e rotas protegidas
- File serving via /api/files/{bucket}/{path} (eliminação DNS)
- Mensagens de erro humanizadas inline (sem pop-ups)
- Middleware tenant detection via headers customizados
- Upload de logos retorna URLs via API
- README atualizado com changelog v1.4 completo
This commit is contained in:
@@ -16,15 +16,25 @@ func TenantDetector(tenantRepo *repository.TenantRepository) func(http.Handler)
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Get host from X-Forwarded-Host header (set by Next.js proxy) or Host header
|
||||
host := r.Header.Get("X-Forwarded-Host")
|
||||
if host == "" {
|
||||
host = r.Header.Get("X-Original-Host")
|
||||
}
|
||||
if host == "" {
|
||||
host = r.Host
|
||||
}
|
||||
// Priority order: X-Tenant-Subdomain (set by Next.js middleware) > X-Forwarded-Host > X-Original-Host > Host
|
||||
tenantSubdomain := r.Header.Get("X-Tenant-Subdomain")
|
||||
|
||||
log.Printf("TenantDetector: host = %s (from headers), path = %s", host, r.RequestURI)
|
||||
var host string
|
||||
if tenantSubdomain != "" {
|
||||
// Use direct subdomain from Next.js middleware
|
||||
host = tenantSubdomain
|
||||
log.Printf("TenantDetector: using X-Tenant-Subdomain = %s", tenantSubdomain)
|
||||
} else {
|
||||
// Fallback to extracting from host headers
|
||||
host = r.Header.Get("X-Forwarded-Host")
|
||||
if host == "" {
|
||||
host = r.Header.Get("X-Original-Host")
|
||||
}
|
||||
if host == "" {
|
||||
host = r.Host
|
||||
}
|
||||
log.Printf("TenantDetector: host = %s (from headers), path = %s", host, r.RequestURI)
|
||||
}
|
||||
|
||||
// Extract subdomain
|
||||
// Examples:
|
||||
@@ -33,17 +43,28 @@ func TenantDetector(tenantRepo *repository.TenantRepository) func(http.Handler)
|
||||
// - dash.localhost -> dash (master admin)
|
||||
// - localhost -> (institutional site)
|
||||
|
||||
parts := strings.Split(host, ".")
|
||||
var subdomain string
|
||||
|
||||
if len(parts) >= 2 {
|
||||
// Has subdomain
|
||||
subdomain = parts[0]
|
||||
|
||||
// If we got the subdomain directly from X-Tenant-Subdomain, use it
|
||||
if tenantSubdomain != "" {
|
||||
subdomain = tenantSubdomain
|
||||
// Remove port if present
|
||||
if strings.Contains(subdomain, ":") {
|
||||
subdomain = strings.Split(subdomain, ":")[0]
|
||||
}
|
||||
} else {
|
||||
// Extract from host
|
||||
parts := strings.Split(host, ".")
|
||||
|
||||
if len(parts) >= 2 {
|
||||
// Has subdomain
|
||||
subdomain = parts[0]
|
||||
|
||||
// Remove port if present
|
||||
if strings.Contains(subdomain, ":") {
|
||||
subdomain = strings.Split(subdomain, ":")[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("TenantDetector: extracted subdomain = %s", subdomain)
|
||||
|
||||
Reference in New Issue
Block a user