AlexKhymenko / ngx-permissions

Permission and roles based access control for your angular(angular 2,4,5,6,7,9+) applications(AOT, lazy modules compatible
MIT License
936 stars 127 forks source link

Update NgxPermissionsGuard to return UrlTree when redirecting instead of using router.navigate #242

Open rms2219 opened 3 weeks ago

rms2219 commented 3 weeks ago

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report 
[x] Feature request
[ ] Documentation issue or request

Current behavior

If the permissions guard is configured with a redirect, and the permissions test fails, the guard uses the Router service to navigate to the configured route.

Expected behavior

As of Angular 7.1, router guards can return a boolean or an instance of UrlTree. By returning a UrlTree instead of using the router to do the navigation, we can prioritize redirects when there are multiple guards applied to a route, both with competing redirects.

Minimal reproduction of the problem with instructions

const authGuard: CanActivateFn|CanMatchFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
  const authService = inject(AuthService);
  const router = inject(Router);
  return authService.isAuthenticated$
    .pipe(
      switchMap(isAuthenticated => {
        if (isAuthenticated) {
          return true;
        }

        return of(router.createUrlTree(['/login']));
    }),
  );
};

// Routes
{
    path: 'home',
    canMatch: [authGuard, ngxPermissionsGuard],
    component: AdminHomeComponent,
    data: {
      permissions: {
        only: ['ROLE_ADMIN'],
        redirectTo: {
          navigationCommands: ['unauthorized'],
          navigationExtras: {
            skipLocationChange: true,
          },
        }
      },
    }
}

The code above will navigate to the "unauthorized" route instead of "login", even though the authGuard guard has priority.

Environment


Angular version: 17.1.1
ngx-permissions version: 17.1.0


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
- [x] Brave version 1.69.160            
rms2219 commented 3 weeks ago

I should add, as a workaround for the time being, I've made use of both canMatch and canActivate route guards on the routes that are affected. I've used my authGuard w/ canMatch and ngxPermissionsGuard with canActivate.