dcb-backoffice/src/app/core/guards/auth.guard.ts

126 lines
3.9 KiB
TypeScript

// src/app/core/guards/auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { RoleService } from '../services/role.service';
import { map, catchError, of, tap, switchMap } from 'rxjs';
export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const authService = inject(AuthService);
const roleService = inject(RoleService);
const router = inject(Router);
console.log('🔐 AuthGuard check for:', state.url);
// Attendre que l'initialisation soit terminée
return authService.getInitializedState().pipe(
switchMap(initialized => {
if (!initialized) {
console.log('⏳ AuthService pas encore initialisé, attente...');
return of(false); // Bloquer en attendant l'initialisation
}
// Vérifier l'authentification
if (authService.isAuthenticated()) {
return of(checkRoleAccess(route, roleService, router, state.url));
}
// Tentative de rafraîchissement du token
const refreshToken = authService.getRefreshToken();
if (refreshToken) {
console.log('🔄 Token expiré, tentative de rafraîchissement...');
return authService.refreshToken().pipe(
tap(() => {
console.log('✅ Token rafraîchi avec succès');
roleService.refreshRoles();
}),
map(() => checkRoleAccess(route, roleService, router, state.url)),
catchError((error) => {
console.error('❌ Échec du rafraîchissement du token:', error);
authService.logout().subscribe();
return of(redirectToLogin(router, state.url, 'session_expired'));
})
);
}
// Redirection vers login
console.log('🔒 Redirection vers login depuis:', state.url);
return of(redirectToLogin(router, state.url, 'not_authenticated'));
}),
catchError(error => {
console.error('❌ Erreur dans le guard d\'auth:', error);
return of(redirectToLogin(router, state.url, 'not_authenticated'));
})
);
}
/**
* Vérifie l'accès basé sur les rôles requis
*/
function checkRoleAccess(
route: ActivatedRouteSnapshot,
roleService: RoleService,
router: Router,
currentUrl: string
): boolean {
const requiredRoles = route.data?.['roles'] as string[];
if (!requiredRoles || requiredRoles.length === 0) {
console.log('✅ Accès autorisé (aucun rôle requis):', currentUrl);
return true;
}
const hasRequiredRole = roleService.hasAnyRole(requiredRoles);
const currentUserRoles = roleService.getCurrentUserRoles();
if (hasRequiredRole) {
console.log('✅ Accès autorisé avec rôles:', currentUrl);
console.log(' Rôles requis:', requiredRoles);
console.log(' Rôles actuels:', currentUserRoles);
return true;
}
console.warn('❌ Accès refusé: rôles insuffisants');
console.warn(' URL demandée:', currentUrl);
console.warn(' Rôles requis:', requiredRoles);
console.warn(' Rôles actuels:', currentUserRoles);
// Rediriger vers la page non autorisée
router.navigate(['/unauthorized'], {
queryParams: {
requiredRoles: requiredRoles.join(','),
currentRoles: currentUserRoles.join(','),
attemptedUrl: currentUrl
},
replaceUrl: true
});
return false;
}
/**
* Redirige vers la page de login avec les paramètres appropriés
*/
function redirectToLogin(
router: Router,
returnUrl: string,
reason: 'not_authenticated' | 'session_expired'
): boolean {
const queryParams: any = {
returnUrl: returnUrl,
reason: reason
};
// Message spécifique selon la raison
if (reason === 'session_expired') {
queryParams.message = 'Votre session a expiré. Veuillez vous reconnecter.';
}
router.navigate(['/auth/sign-in'], {
queryParams,
replaceUrl: true
});
return false;
}