Home > Blockchain >  Custom Page Permission using Angular 11
Custom Page Permission using Angular 11

Time:12-31

I am working on an application in which I am implementing custom permission. There is subscription-based permission that I can't check in auth guard which will be static and I have implemented helper for permission which checks for route and then check it in user subscription for that route and then redirected to any of the pages on role permission. It is working fine but I need a better approach to implement it with clean code. Here is my implementation

Home Component

import { Component, OnInit } from "@angular/core";
import { Location } from '@angular/common';   
import { AuthService } from "src/app/services/apiServices/auth.service";

@Component({
  selector: "app-home",
  templateUrl: "./home.component.html"
})
export class HomeComponent implements OnInit {
  constructor(private readonly location: Location, private readonly authService : AuthService ) {
  }
  ngOnInit() {
    this.authService.getPermission(this.location.path());
  }
}

Auth Service Code

getPermission(currentRoute: string) {
    this.userPermissions = this.loggedInUserSubscriptionDetails$.subscribe(sub => {
      if (sub) {
        if (sub.MenuPermissioList.map(x => x.url).indexOf(currentRoute) === -1) {
          this.router.navigate(["/finance-analysis/not-authorized"]);
          return;
        }else{
          console.log('exists');
        }
      }
    });

  }

This code is basically getting a current location path and then checking that path in subscription MenuPermissioList if it exists then it allows to open up the page otherwise it redirected to unauthorized.

I don't want to use this code data : {roles: [ApplicationRolesEnum.CompanyAdmin]} because I have to add or remove roles from data to allow that user for a specific page and it is basically static binding. Here I have added this check and it is working fine but my permission may vary from user to user. Which makes it difficult to maintain.

     {
        path: "home",
        canActivate: [AuthGuard, SubscriptionGuard],data : {roles: [ApplicationRolesEnum.CompanyAdmin, ApplicationRolesEnum.ExternalUser]},
        loadChildren: () => import("src/app/pages/dashboard/dashboard.module").then(m => m.DashboardModule)
      },

CodePudding user response:

You could try following approach. I did not test it now and have written it off the top of my head but it is based on an approach I used in one project.

Basically you would still use a Guard for this but load the permissions from your service dynamically and based on them either let the user activate the page or redirect to the Unauthorized page. CanActivate subscribes to the Observable for you so you don't have to manage any subscription manually.

import { AuthService } from "src/app/services/apiServices/auth.service";

function getPathFromRoot(route: ActivatedRouteSnapshot) {
  return route.pathFromRoot
    .map(p => p.url.map(segment => segment.toString()).join('/'))
    .join('/');
}

@Injectable()
export class SubscriptionGuard implements CanActivate {

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

  canActivate(activatedRoute: ActivatedRouteSnapshot): Observable<boolean> {
    return this.authService.loggedInUserSubscriptionDetails$.pipe(
      take(1),
      map((sub) => {
        if (!sub) {
          return false;
        }
        return sub.MenuPermissioList.map(x => x.url).includes(getPathFromRoot(activatedRoute));
      }),
      tap(hasPermission => hasPermission ? undefined : this.router.navigate(['/finance-analysis/not-authorized']))
    );
  }
}
  • Related