feat: Implement multi-tenancy support in middleware and security layers

- Enhanced TenantMiddleware to validate tenant information from JWT tokens.
- Added LicenseValidationMiddleware to check tenant licenses before processing requests.
- Updated security utilities to extract tenant information from tokens and validate company access.
- Introduced CompanyStore to manage active company state and handle company switching in the frontend.
- Modified API routes to include company_id in requests for better resource management.
- Improved logging and error handling throughout the middleware and API layers.
- Updated frontend components to reflect changes in company management and selection.
- Added new API route for fetching user's companies with proper authentication handling.
This commit is contained in:
2025-11-11 14:00:56 -06:00
parent e1eb6bbd01
commit 52b8fcd434
242 changed files with 7067 additions and 3274 deletions

View File

@@ -173,8 +173,11 @@ export const initKeycloak = async (): Promise<boolean> => {
}
};
// Variable para rastrear el tenant anterior
let previousTenantId: number | undefined = undefined;
/**
* Actualiza el estado de autenticación
* Actualiza el estado de autenticación con los datos de Keycloak
*/
const updateAuthState = async () => {
if (!keycloakInstance?.authenticated) {
@@ -189,19 +192,36 @@ const updateAuthState = async () => {
const roles = tokenParsed?.realm_access?.roles || [];
const tenantId = tokenParsed?.tenant_id || tokenParsed?.attributes?.tenant_id;
const newTenantId = tenantId ? parseInt(tenantId) : undefined;
// Detectar si cambió el tenant
const tenantChanged = previousTenantId !== undefined && previousTenantId !== newTenantId;
const user: User = {
id: profile.id || '',
username: profile.username || '',
email: profile.email,
name: `${profile.firstName || ''} ${profile.lastName || ''}`.trim(),
tenantId: tenantId ? parseInt(tenantId) : undefined,
tenantId: newTenantId,
roles
};
authStore.setAuthenticated(true);
authStore.setUser(user);
authStore.setToken(token);
// Si cambió el tenant, limpiar el store de compañías
if (tenantChanged && browser) {
try {
const { companyStore } = await import('./stores/company.svelte');
companyStore.clear();
} catch (error) {
console.error('Error al limpiar store de compañías:', error);
}
}
// Actualizar el tenant anterior
previousTenantId = newTenantId;
} catch (error) {
console.error('Error actualizando estado de autenticación:', error);
authStore.reset();
@@ -361,6 +381,14 @@ export const logout = async () => {
}
}
// Limpiar store de compañías
try {
const { companyStore } = await import('./stores/company.svelte');
companyStore.clear();
} catch (error) {
console.error('Error al limpiar store de compañías:', error);
}
// Limpiar estado local
authStore.reset();
localStorage.removeItem('access_token');