Skip to content

Commit 867478f

Browse files
committed
feat(auth-guard): add support for specifying a UrlTree or a string to redirect to
Closes #2287, #2144
1 parent 73d5a1f commit 867478f

File tree

2 files changed

+13
-11
lines changed

2 files changed

+13
-11
lines changed

docs/auth/router-guards.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import { customClaims } from '@angular/fire/auth-guard';
8080

8181
// This pipe will only allow users with the editor role to access the route
8282
// { path: 'articles/:id/edit', component: ArticleEditComponent, ...canActivate(editorOnly) }
83-
const editorOnly = () => pipe(customClaims, map(claims => claims.role === "editor"));
83+
const editorOnly = () => pipe(customClaims, map(claims => claims.role === 'editor'));
8484
```
8585

8686
### Using router state
@@ -98,5 +98,5 @@ const onlyAllowSelf = (next) => map(user => !!user && next.params.userId === use
9898

9999
// Only allow navigation to the route if the user has a custom claim matching :accountId
100100
// { path: 'accounts/:accountId/billing', component: BillingDetailsComponent, ...canActivate(accountAdmin) }
101-
const accountAdmin = (next) => pipe(customClaims, map(claims => claims[`account-${next.params.accountId}-role`] === "admin"));
101+
const accountAdmin = (next) => pipe(customClaims, map(claims => claims[`account-${next.params.accountId}-role`] === 'admin'));
102102
```

src/auth-guard/auth-guard.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Injectable, Inject, Optional, NgZone } from '@angular/core';
22
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
33
import { Observable, of, pipe, UnaryFunction } from 'rxjs';
4-
import { map, switchMap, take, observeOn, shareReplay } from 'rxjs/operators'
4+
import { map, switchMap, take, observeOn, shareReplay } from 'rxjs/operators';
55
import { User } from 'firebase/app';
66
import { ɵAngularFireSchedulers, FirebaseOptions, FirebaseAppConfig, FIREBASE_OPTIONS, FIREBASE_APP_NAME, ɵfirebaseAppFactory } from '@angular/fire';
77

88
export type AuthPipeGenerator = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => AuthPipe;
9-
export type AuthPipe = UnaryFunction<Observable<User|null>, Observable<boolean|any[]>>;
9+
export type AuthPipe = UnaryFunction<Observable<User|null>, Observable<boolean|string|any[]>>;
1010

1111
@Injectable({
1212
providedIn: 'any'
@@ -16,8 +16,8 @@ export class AngularFireAuthGuard implements CanActivate {
1616
authState: Observable<User|null>;
1717

1818
constructor(
19-
@Inject(FIREBASE_OPTIONS) options:FirebaseOptions,
20-
@Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig:string|FirebaseAppConfig|null|undefined,
19+
@Inject(FIREBASE_OPTIONS) options: FirebaseOptions,
20+
@Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig: string|FirebaseAppConfig|null|undefined,
2121
zone: NgZone,
2222
private router: Router
2323
) {
@@ -40,21 +40,23 @@ export class AngularFireAuthGuard implements CanActivate {
4040
return this.authState.pipe(
4141
take(1),
4242
authPipeFactory(next, state),
43-
map(can => typeof can == "boolean" ? can : this.router.createUrlTree(<any[]>can))
43+
map(can => typeof can === 'boolean' ? can :
44+
Array.isArray(can) ? this.router.createUrlTree(can) : this.router.parseUrl(can)
45+
)
4446
);
4547
}
4648

4749
}
4850

4951
export const canActivate = (pipe: AuthPipeGenerator) => ({
50-
canActivate: [ AngularFireAuthGuard ], data: { authGuardPipe: pipe }
52+
canActivate: [ AngularFireAuthGuard ], data: { authGuardPipe: pipe }
5153
});
5254

5355
export const loggedIn: AuthPipe = map(user => !!user);
5456
export const isNotAnonymous: AuthPipe = map(user => !!user && !user.isAnonymous);
5557
export const idTokenResult = switchMap((user: User|null) => user ? user.getIdTokenResult() : of(null));
5658
export const emailVerified: AuthPipe = map(user => !!user && user.emailVerified);
5759
export const customClaims = pipe(idTokenResult, map(idTokenResult => idTokenResult ? idTokenResult.claims : []));
58-
export const hasCustomClaim = (claim:string) => pipe(customClaims, map(claims => claims.hasOwnProperty(claim)));
59-
export const redirectUnauthorizedTo = (redirect: any[]) => pipe(loggedIn, map(loggedIn => loggedIn || redirect));
60-
export const redirectLoggedInTo = (redirect: any[]) => pipe(loggedIn, map(loggedIn => loggedIn && redirect || true));
60+
export const hasCustomClaim = (claim: string) => pipe(customClaims, map(claims => claims.hasOwnProperty(claim)));
61+
export const redirectUnauthorizedTo = (redirect: string|any[]) => pipe(loggedIn, map(loggedIn => loggedIn || redirect));
62+
export const redirectLoggedInTo = (redirect: string|any[]) => pipe(loggedIn, map(loggedIn => loggedIn && redirect || true));

0 commit comments

Comments
 (0)