好,我有一条路线:站点/仪表板/订单
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, NgxPermissionsGuard],
data: {
permissions: {
only: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
}
在我的应用程序组件中,我检查用户是否已通过身份验证,如果是,请从api获取角色并使用NgxPermissions模块加载权限
app.component.ts(在构造函数中:):
constructor(private services) {
this.checkAuth();
}
checkAuth() {
apiService.checkAuth().subscribe((value: boolean) => {
if (value) {
// get roles with another api call
apiService.getRoles().subscribe(roles => {
this.permissionsService.loadPermissions(roles);
});
}
});
}
我知道这不是在另一个订阅中拥有订阅的最佳方法,但是现在这无关紧要。
如果我从首页访问该网站,则该问题不存在,因为:
转到网站/主页=> checkAuth()已执行并且有足够的时间获取api结果=>加载角色
导航到仪表板/订单=>角色已经从上一步(如果我的协商速度不太快),以及在路由时转到路径“仪表板”并仅使用权限检查数据['admin','dashboard'],这将允许我访问路线,因为存在角色。
但是,如果我尝试直接访问站点/仪表板/订单:
如何在访问路由和验证权限之前等待加载角色?
我只需要获得一次角色(第一次访问应用程序时),而不必为每个路由模块获得角色。是否可以在路由模块中侦听可观察对象?
不久,我需要在路由之前加载角色。
谢谢
我找到了一个解决方案,我不知道它是否是最好的,但是它可以正常工作:
在NgxPermissionsGuard处放弃并创建另一个实现CanActivate并发送roles和redirectTo作为两个守护程序的参数的守护程序“ PermissionsGuard”。
Routing:
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, PermissionsGuard],
data: {
roles: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
PermissionsGuard.ts:
export class PermissionsGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const routeRoles = next.data.roles as Array<string>;
const redirectTo = next.data.redirectTo;
const userName = localStorage.getItem('userName');
return this.getRoles(userName, routeRoles, redirectTo);
}
getRoles(userName: string, routeRoles: string[], redirectTo: string) {
let userRoles = [];
const roles = this.permissionsService.getPermissions();
for (const key in roles) {
userRoles.push(key);
}
if (userRoles.length > 0) {
return this.isInRole(userRoles, routeRoles, redirectTo);
} else {
// api call, get user roles
return this.isInRole(apiResult, routeRoles, redirectTo);
}
// in both cases, if boolean value is false
this.router.navigateByUrl(navigateTo);
}
}
isInRole(userRoles: string[], routeRoles: string[], redirectTo: string) {
// let canAccessRoute = false;
// check if routeRoles contain any element of userRoles
if (canAccessRoute) {
return true;
} else {
this.router.navigateByUrl(redirectTo);
}
}
两个守护者(AuthGuard和PermissionsGuard)都需要返回true才能让用户访问路由。一些数据是承诺的结果,因此使用返回方法需要这些数据。