126 lines
3.9 KiB
TypeScript
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;
|
|
} |