Search code examples
angularangular-routingangular-guards

CanActivate is deprecated. How to refactor?


Angular - CanActivate is deprecated. How to refactor?

I found the documentation on the site very scarce and I am not able to adapt it to use CanActivateFn

How to suit to use CanActivateFn?

Follow my code:

AuthGuard:

export class AuthGuard implements CanActivate {
  constructor(private router: Router, private tokenStorage: TokenStorageService) {}

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.tokenStorage.isTokenExpired()) {
      this.router.navigateByUrl('/forbidden');
      return false;
    }

    const roles = next.data['permittedRoles'] as Array<string>;
    if (roles && !this.roleMatch(roles)) {
      this.router.navigateByUrl('/login');
      return false;
    }

    return true;
  }

  roleMatch(allowedRoles: string[]): boolean {
    const userRole = this.tokenStorage.getUserToken().role;
    return allowedRoles.includes(userRole);
  }
}

rounting:

...
    {
    path: 'submissionSumario', loadChildren: () => import('./sumarios/submission-sumario/submission-sumario.module').then(m => m.SubmissionSumarioModule),
    canActivate: [AuthGuard],
    data: {
      permittedRoles: ['admin', 'usercommon', 'useradvanced', 'guest'],
      title: 'Submission Article',
      robots: 'noindex',
      type: 'website'
    }
  },
...

Version:

Angular CLI: 15.2.4
Node: 18.13.0
Package Manager: npm 9.2.0
OS: win32 x64

Angular: 15.2.3
... animations, cdk, common, compiler, compiler-cli, core, forms
... material, platform-browser, platform-browser-dynamic
... platform-server, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1502.4
@angular-devkit/build-angular   15.2.4
@angular-devkit/core            15.2.4
@angular-devkit/schematics      15.2.4
@angular/cli                    15.2.4
@nguniversal/builders           15.2.0
@nguniversal/express-engine     15.2.0
@schematics/angular             15.2.4
rxjs                            7.8.0
typescript                      4.9.5

Solution

  • I was able to adapt my class to use the CanActivateFn type function return.

    export const AuthGuard: CanActivateFn = (
      route: ActivatedRouteSnapshot,
      state: RouterStateSnapshot
    ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree => {
    
      const router: Router = inject(Router);
      const tokenStorage: TokenStorageService = inject(TokenStorageService);
    
      if (tokenStorage.isTokenExpired()) {
        return router.navigate(['forbidden']);    
      }
      else {
        const roles = route.data['permittedRoles'] as Array<string>;
        const userRole = tokenStorage.getUserToken().role;
    
        if (roles && !roles.includes(userRole)) {
          return router.navigate(['login']);
        }
        else
          return true;
      }
    
    }