Angular 路由器:根据用户的角色导航到不同的路由

Angular router: navigating to different routes according to the user's role

我正在编写一个具有以下结构的模拟电子商务应用程序:

基本工作流程应该如下:

  1. 用户导航到根路径/
  2. 应用程序检测到他们未登录,因此将他们重定向到 /signin
  3. 他们输入凭据并按 登录
  4. 如果认证成功,
    1. 如果用户是管理员,他们将被重定向到 /admin
      1. admin-router.module.ts 将它们重定向到 /admin.
      2. 的某个子路径
    2. 如果用户是客户,他们将被重定向到 /customer
      1. customer-router.module.ts 将他们重定向到 /customer/catalog/<default category ID>.
      2. 他们将一些产品放入购物车并继续/customer/checkout
      3. 他们下订单并被重定向到 /customer/thankyou

我不确定的是如何在成功登录后完成重定向。显然,它必须分两个阶段完成:首先是某些公共路径,例如 /,然后是 /customer/admin,具体取决于用户的角色。第二阶段可能需要由 app-routing.module.ts 处理,也许需要使用守卫,但我不确定具体该怎么做。

编辑 (2021-04-20)

问题可以归纳为:

我需要的是一种方法(最好是声明式的)根据其状态将应用程序从 / 重定向到以下路径之一:

State Path
Logged out /auth
Logged in as a customer /customer
Logged in as an admin /admin

您可以创建一些虚拟组件并使用处理正确导航的守卫来保护它。像这样:

[
  {
    path: 'loggedin',
    component: DummyComponent,
    canActivate: [HandleLoginGuard]
  },
  {
    path: 'admin',
    component: AdminComponent,
  },
  {
    path: 'customer',
    component: CustomerComponent,
  }
]


@Injectable()
class HandleLoginGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) {
    if(isAdmin()){
        route.navigate(/admin);
    }else{
        route.navigate(/customer);
    }
    return false;
  }
}

这样你就可以把逻辑放在一个守卫而不是登录组件中。

我最后做的是这样的:

// app-routing.module.ts

const routes: Routes = [
  {
    path: '',
    canActivate: [AuthorizationGuard],
    children: [],
  },
  { path: '**', component: NotFoundPage },
];
// authorization.guard.ts

@Injectable({
  providedIn: 'root',
})
export class AuthorizationGuard implements CanActivate {

  constructor(private router: Router, private authService: AuthService) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): UrlTree {
    const user = this.authService.getLoggedInUser();
    return (
      (user?.role === 'admin' && this.router.parseUrl('/admin')) ||
      (user?.role === 'customer' && this.router.parseUrl('/customer')) ||
      this.router.parseUrl('/auth')
    );
  }

}