[将最终路由添加到url时在加载模块之前加载权限

问题描述 投票:0回答:1

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

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

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

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

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

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

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

谢谢

angular redirect permissions routing roles
1个回答
0
投票

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

在NgxPermissionsGuard处放弃并创建另一个实现CanActivate并发送rolesredirectTo作为两个守护程序的参数的守护程序“ 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才能让用户访问路由。一些数据是承诺的结果,因此使用返回方法需要这些数据。

© www.soinside.com 2019 - 2024. All rights reserved.