1

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
Leandro
  • 91
  • 1
  • 9

2 Answers2

2

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;
  }

}
Leandro
  • 91
  • 1
  • 9
0

Based on angular's documentation, you should no longer have a Guard class when using the route guard, now only a regular function of type CanActivateFn will do.

Example inspired from Angular's official docs:

const canActivateTeam: CanActivateFn =
(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
  return inject(PermissionsService).canActivate(inject(UserToken), route.params.id);
};

And in your routing file:

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

}, ...