在访问最终路由到 url 时加载模块之前加载权限

Load permissions before loading module when is accesed final route into url

好的,我有一条路线:site/dashboards/orders

  {
    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);
          });  
     }
   });
}

我知道这不是在另一个订阅中订阅的最佳方式,但现在这并不重要。

如果我从第一页访问该站点,则问题不存在,因为:

但是,如果我尝试直接访问 site/dashboards/orders:

如何在访问路由和验证权限之前等待加载角色?

我只需要获取角色一次(在第一次访问应用程序时),而不是为每个路由模块获取角色。可以在路由模块中监听 observables 吗?

不久,我需要在路由之前加载角色。

谢谢

我找到了一个解决方案,我不知道是否是最好的,但它的工作原理:

放弃 NgxPermissionsGuard 并创建另一个实现 CanActivate 的守卫 "PermissionsGuard" 并发送 rolesredirectTo 作为两个守卫的参数.

路由:

{
    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);
    }
  }

  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)都需要 return true 让用户访问路由。一些数据是承诺的结果,因此需要使用 returning 方法。