Skip to content

Commit 04e5d4d

Browse files
committed
Add redirectUrl support to PermissionGuard
PermissionGuard now supports redirecting to a specified URL when access is denied and a redirectUrl is provided in route data. Updated guard logic to use map instead of filter/tap, and added corresponding unit tests to verify redirect behavior.
1 parent 3cc2fb5 commit 04e5d4d

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import {
44
CanActivateFn,
55
Router,
66
RouterStateSnapshot,
7+
UrlTree,
78
} from '@angular/router';
89
import { HttpErrorResponse } from '@angular/common/http';
910
import { Observable, of } from 'rxjs';
10-
import { filter, take, tap } from 'rxjs/operators';
11+
import { map, take } from 'rxjs/operators';
1112
import { AuthService, IAbpGuard } from '../abstracts';
1213
import { findRoute, getRoutePath } from '../utils/route-utils';
1314
import { RoutesService, PermissionService, HttpErrorReporterService } from '../services';
@@ -25,7 +26,7 @@ export class PermissionGuard implements IAbpGuard {
2526
protected readonly permissionService = inject(PermissionService);
2627
protected readonly httpErrorReporter = inject(HttpErrorReporterService);
2728

28-
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
29+
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
2930
let { requiredPolicy } = route.data || {};
3031

3132
if (!requiredPolicy) {
@@ -38,12 +39,19 @@ export class PermissionGuard implements IAbpGuard {
3839
}
3940

4041
return this.permissionService.getGrantedPolicy$(requiredPolicy).pipe(
41-
filter(Boolean),
4242
take(1),
43-
tap(access => {
44-
if (!access && this.authService.isAuthenticated) {
43+
map(access => {
44+
if (access) return true;
45+
46+
if (route.data?.['redirectUrl']) {
47+
return this.router.parseUrl(route.data['redirectUrl']);
48+
}
49+
50+
if (this.authService.isAuthenticated) {
4551
this.httpErrorReporter.reportError({ status: 403 } as HttpErrorResponse);
4652
}
53+
54+
return false;
4755
}),
4856
);
4957
}
@@ -77,12 +85,19 @@ export const permissionGuard: CanActivateFn = (
7785
}
7886

7987
return permissionService.getGrantedPolicy$(requiredPolicy).pipe(
80-
filter(Boolean),
8188
take(1),
82-
tap(access => {
83-
if (!access && authService.isAuthenticated) {
89+
map(access => {
90+
if (access) return true;
91+
92+
if (route.data?.['redirectUrl']) {
93+
return router.parseUrl(route.data['redirectUrl']);
94+
}
95+
96+
if (authService.isAuthenticated) {
8497
httpErrorReporter.reportError({ status: 403 } as HttpErrorResponse);
8598
}
99+
100+
return false;
86101
}),
87102
);
88103
};

npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ describe('authGuard', () => {
3939
component: DummyComponent,
4040
canActivate: [permissionGuard],
4141
},
42+
{
43+
path: 'redirect-test',
44+
component: DummyComponent,
45+
canActivate: [permissionGuard],
46+
data: {
47+
requiredPolicy: 'TestPolicy',
48+
redirectUrl: '/zibzib',
49+
},
50+
},
4251
];
4352

4453
beforeEach(() => {
@@ -103,4 +112,12 @@ describe('authGuard', () => {
103112
await RouterTestingHarness.create('/zibzib');
104113
expect(TestBed.inject(Router).url).toEqual('/zibzib');
105114
});
115+
116+
it('should redirect to redirectUrl when the grantedPolicy is false and redirectUrl is provided', async () => {
117+
permissionService.getGrantedPolicy$.andReturn(of(false));
118+
await RouterTestingHarness.create('/redirect-test');
119+
120+
expect(TestBed.inject(Router).url).toEqual('/zibzib');
121+
expect(httpErrorReporter.reportError).not.toHaveBeenCalled();
122+
});
106123
});

0 commit comments

Comments
 (0)