Files
aggios.app/front-end-agency/lib/server-api.ts
Erik Silva 2f1cf2bb2a 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
2025-12-13 15:05:51 -03:00

80 lines
2.4 KiB
TypeScript

/**
* Server-side API functions
* Estas funções são executadas APENAS no servidor (não no cliente)
*/
import { cookies, headers } from 'next/headers';
const API_BASE_URL = process.env.API_INTERNAL_URL || 'http://backend:8080';
interface AgencyBrandingData {
logo_url?: string;
primary_color?: string;
secondary_color?: string;
name?: string;
}
/**
* Busca os dados de branding da agência no servidor
* Usa o subdomínio do request para identificar a agência
*/
export async function getAgencyBranding(): Promise<AgencyBrandingData | null> {
try {
// Pegar o hostname do request
const headersList = await headers();
const hostname = headersList.get('host') || '';
const subdomain = hostname.split('.')[0];
if (!subdomain || subdomain === 'localhost' || subdomain === 'www') {
return null;
}
// Buscar dados da agência pela API
const url = `${API_BASE_URL}/api/tenant/config?subdomain=${subdomain}`;
console.log(`[ServerAPI] Fetching agency config from: ${url}`);
const response = await fetch(url, {
cache: 'no-store', // Sempre buscar dados atualizados
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
console.error(`[ServerAPI] Failed to fetch agency branding for ${subdomain}: ${response.status}`);
return null;
}
const data = await response.json();
console.log(`[ServerAPI] Agency branding data for ${subdomain}:`, JSON.stringify(data));
return data as AgencyBrandingData;
} catch (error) {
console.error('[ServerAPI] Error fetching agency branding:', error);
return null;
}
}
/**
* Busca apenas o logo da agência (para metadata)
*/
export async function getAgencyLogo(): Promise<string | null> {
const branding = await getAgencyBranding();
return branding?.logo_url || null;
}
/**
* Busca as cores da agência (para passar ao client component)
*/
export async function getAgencyColors(): Promise<{ primary: string; secondary: string } | null> {
const branding = await getAgencyBranding();
if (branding?.primary_color && branding?.secondary_color) {
return {
primary: branding.primary_color,
secondary: branding.secondary_color,
};
}
return null;
}