How to prevent actions by user role in Angular

十年热恋 提交于 2020-06-12 08:49:04

问题


I already have an AuthService to authenticate user on login and AuthGuard to prevent access if not logged in.

Some pages I restrict access by UserProfile/Role but now I need to prevent actions on page.

I have roles like "Admin, Manager, Support and Agent", from greater to lower.

How to set level only to Manager or Above to edit content on a page that all can access (Support and Agent restrict to view only)?

This is my current canActivate method:

canActivate(route: ActivatedRouteSnapshot) {

  const currentUser = JSON.parse(localStorage.getItem('currentUser'));
  if (currentUser) {
    // check if route is restricted by role
    if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
      // role not authorised so redirect to home page
      this.router.navigate(['/']);
      return false;
    }
    // authorised so return true
    return true;
  }
  // not logged in so redirect to login page
  this.router.navigate(['auth/login']);
  return false;
}

And this is my module routing.module.ts

const routes: Routes = [{
  path: '',
  component: ReportsComponent,
  canActivateChild: [AuthGuard],
  children: [
    {
      path: 'blocked-users',
      component: BlockedUsersComponent,
      data: { roles: [Role.admin, Role.manager, Role.suporte, Role.agent] },
      children: [
        { ... 

Need to fix these two topics:

1) Line data: { roles: [] } I want to pass only the lower level (like Agent);

2) Inside component tell that only Manager can edit data (or just disable a button if Role == Support or Agent)


回答1:


Break out your authorisation code into a service that both your guard and other services can make use of (DRY!). From there, the logic is the same for checking roles around the entire site.

@Injectable()
export class RoleAuthorisationService {
  public isAuthorised(roles: Role[]): boolean {
    const currentUser = JSON.parse(localStorage.getItem('currentUser'));
    if (!currentUser) return false;
    return roles.indexOf(currentUser.role) >= 0)
  }
}

The guard will be making use of it, but then you can just prevent usage of any part of your pages by making your own check against that authorisation service.

Your guard (very approximated because it's 23:32 and I want to go to bed):

export class YourGuard {

  constructor(private readonly auth: RoleAuthorisationService) {}

  canActivate(route: ActivatedRouteSnapshot) {
    if (route.data.roles && !this.auth.isAuthorised(route.data.roles)) {
      // role not authorised so redirect to home page
      this.router.navigate(['/']);
      return false;
    } else {
      // authorised so return true
      return true;
    }

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

Want to hide an 'Edit' button on the screen?

Template:

<h1>Some details<h1>
<button *ngIf="canEdit" (click)="enableEditing()>Edit</button>
<p>Details etc etc...</P>

Ts:

export class SomeComponent {
  private readonly editors: Role[] = [Role.Agent, Role.Administrator];

  constructor(private readonly auth: RoleAuthorisationService) {}

  public get canEdit(): boolean { return this.auth.isAuthorised(this.editors); }
}

Edit: To add an answer for your more specific question of locking things unless a user is 'a manager or higher', you can either (as above) be very specific about the exact roles that can access the functionality, or you can use enums. So long as your enums are specified in order, you can do basic > = < checks.

export enum Role {
  Admin = 1,
  Manager = 2,
  Support = 3,
  Peon = 4
}

...

return CurrentUser.Role <= Role.Manager;


来源:https://stackoverflow.com/questions/57399419/how-to-prevent-actions-by-user-role-in-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!