【问题标题】:Load permissions before loading module when is accesed final route into url在将最终路由访问到 url 时,在加载模块之前加载权限
【发布时间】:2020-07-10 14:56:05
【问题描述】:

好的,我有一条路线:站点/仪表板/订单

  {
    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', 'dashboards'],这将允许我访问路线,因为 角色存在。

但是,如果我尝试直接访问网站/仪表板/订单:

  • app.component.ts 是 Angular 中第一个加载的组件,所以会调用 checkAuth() 方法。但是因为这是一个可观察的,将传递给 完成之前的下一步操作(检查路由数据权限)。 由于未加载角色,该应用会将我重定向到“主页”。

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

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

很快,我需要在路由之前加载角色。

谢谢

【问题讨论】:

    标签: angular redirect permissions routing roles


    【解决方案1】:

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

    放弃 NgxPermissionsGuard 并创建另一个守卫“PermissionsGuard”,它实现 CanActivate 并在两个守卫中发送 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)都需要返回 true 才能让用户访问路由。有些数据是 promise 的结果,因此需要使用返回方法。

    【讨论】:

      猜你喜欢
      • 2017-06-06
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2017-01-27
      • 1970-01-01
      • 2019-07-31
      相关资源
      最近更新 更多