AuthGuard на основе назначенного ресурса, а не по роли - PullRequest
0 голосов
/ 16 апреля 2020

Я делаю веб-приложение в Angular 8, и у меня есть требование показать / скрыть меню на основе назначенного ресурса. Ресурс - это меню / модуль / функция, как хотите. Допустим, у меня есть 3 меню: встречи, уведомления и чаты. Каждый из них является «ресурсом» для клиента, но для нас это особенность проекта Angular с его собственным модулем и маршрутизацией.

Я прочитал несколько статей, в которых показана логика c для активации маршрута на основе ролей (, как этот ), но я не могу заставить его работать, используя наш подход.

Когда пользователь входит на сайт, мы получать информацию с массивом «ресурсов», которые пользователю разрешено просматривать / получать к ним доступ.

{
   firstName: "Mario"
   resources: ["Appointments", "Notifications", "Chats"]
}

Мы сохраняем эту информацию в сервисе и можем получать данные в любое время.

Как я уже сказал, мы разделили каждый ресурс с его собственным модулем и маршрутизацией, так что это наш app-routing.module.ts :

const routes: Routes = [
  {path: '', redirectTo: 'appointment/administration', pathMatch: 'full'},

  {
    path: '',
    component: AdminLayoutComponent,
    canActivate: [AuthGuard], // Checking to see if you are logged in.
    children: [
      {
        path: '',
        canActivateChild: [AuthGuard], // Checking to see if you are logged in.
        children: [
          {
            path: '',
            loadChildren: () => import('./modules/appointment/appointment.module').then(m => m.AppointmentModule),
            canLoad: [AuthGuard] // Only load the module if the user is allow to access.
          },
          {
            path: '',
            loadChildren: () => import('./modules/chat/chat.module').then(m => m.ChatModule),
            canLoad: [AuthGuard] // Only load the module if the user is allow to access.
          },
          {
            path: '',
            loadChildren: () => import('./modules/notification/notification.module').then(m => m.NotificationModule),
            canLoad: [AuthGuard] // Only load the module if the user is allow to access.
          },
        ]
      }
    ]
  },
];

Маршрутизация каждого модуля выглядит следующим образом: например, модулем уведомлений :

const routes: Routes = [
  {
    path: 'notification',
    // I have added this trying to do the resource based route activation.
    // This is the name of this resource to look at it in our AuthGuard.
    data: {
      resource: 'Notifications'
    },
    children: [
      {
        path: 'registry',
        component: NotificationRegistryComponent
      },
      {
        path: 'history',
        component: NotificationHistoryComponent
      },
    ]
  },
];

Наш последний шаг - AuthGuard.

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {

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

  /**
   * Requiring authentication.
   */
  checkLogin(route?: ActivatedRouteSnapshot): boolean {
    const currentUser = this.authService.currentUserValue;
    if (currentUser) {
      // check if route is restricted by resource
      if (route && route.data && route.data.resource && this.checkAuthorization(route, currentUser.resources)) {
        // resource not authorised so redirect to home page
        this.router.navigateByUrl('/');
        return false;
      }

      // authorised so return true
      return true;
    }

    // not logged in so redirect to login page
    this.router.navigateByUrl('/auth/login');
    return false;
  }

  /**
   * Checks if the user is allow to access this resource.
   */
  checkAuthorization(route: ActivatedRouteSnapshot, allowedResources: string[]): boolean {
    const currentResource: string = route.data.resource;
    return allowedResources.some(r => r.toLowerCase() === currentResource.toLowerCase());
  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return this.checkLogin(route);
  }

  canActivateChild(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return this.canActivate(childRoute, state);
  }

  canLoad(
    route: Route,
    segments: UrlSegment[]
  ): Observable<boolean> | Promise<boolean> | boolean {
    return this.checkLogin();
  }

}

Мы можем войти в наши разрешенные ресурсы, но, мы также можем войти в недопустимые ресурсы и, конечно же, Файл загружен.

Наша цель - иметь доступ только к нашим разрешенным ресурсам, и если вы пытаетесь получить доступ к запрещенному ресурсу, введя URL-адрес вручную в браузере, избегайте загрузки модуля и перенаправления. пользователь на один из его разрешенных ресурсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...