Skip to content

Commit

Permalink
feat(auth-guard): add support for specifying a string to redirect to (
Browse files Browse the repository at this point in the history
#2448)

* feat(auth-guard): add support for specifying a `string` to redirect to

Closes #2287, #2144

* refactor(auth-guard): make ternary easier to read

Co-authored-by: James Daniels <jamesdaniels@google.com>
  • Loading branch information
EdricChan03 and jamesdaniels authored Nov 11, 2020
1 parent dbf31d9 commit fe31191
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 7 deletions.
4 changes: 2 additions & 2 deletions docs/auth/router-guards.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ import { customClaims } from '@angular/fire/auth-guard';

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

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

// Only allow navigation to the route if the user has a custom claim matching :accountId
// { path: 'accounts/:accountId/billing', component: BillingDetailsComponent, ...canActivate(accountAdmin) }
const accountAdmin = (next) => pipe(customClaims, map(claims => claims[`account-${next.params.accountId}-role`] === "admin"));
const accountAdmin = (next) => pipe(customClaims, map(claims => claims[`account-${next.params.accountId}-role`] === 'admin'));
```
19 changes: 14 additions & 5 deletions src/auth-guard/auth-guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@angular/fire';

export type AuthPipeGenerator = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => AuthPipe;
export type AuthPipe = UnaryFunction<Observable<firebase.User|null>, Observable<boolean|any[]>>;
export type AuthPipe = UnaryFunction<Observable<firebase.User|null>, Observable<boolean|string|any[]>>;

export const loggedIn: AuthPipe = map(user => !!user);

Expand Down Expand Up @@ -54,14 +54,23 @@ export class AngularFireAuthGuard implements CanActivate {
return this.authState.pipe(
take(1),
authPipeFactory(next, state),
map(can => typeof can === 'boolean' ? can : this.router.createUrlTree(can as any[]))
map(can => {
if (typeof can === 'boolean') {
return can;
} else if (Array.isArray(can)) {
return this.router.createUrlTree(can);
} else {
// TODO(EdricChan03): Add tests
return this.router.parseUrl(can);
}
})
);
}

}

export const canActivate = (pipe: AuthPipeGenerator) => ({
canActivate: [ AngularFireAuthGuard ], data: { authGuardPipe: pipe }
canActivate: [ AngularFireAuthGuard ], data: { authGuardPipe: pipe }
});


Expand All @@ -71,7 +80,7 @@ export const emailVerified: AuthPipe = map(user => !!user && user.emailVerified)
export const customClaims = pipe(idTokenResult, map(idTokenResult => idTokenResult ? idTokenResult.claims : []));
export const hasCustomClaim: (claim: string) => AuthPipe =
(claim) => pipe(customClaims, map(claims => claims.hasOwnProperty(claim)));
export const redirectUnauthorizedTo: (redirect: any[]) => AuthPipe =
export const redirectUnauthorizedTo: (redirect: string|any[]) => AuthPipe =
(redirect) => pipe(loggedIn, map(loggedIn => loggedIn || redirect));
export const redirectLoggedInTo: (redirect: any[]) => AuthPipe =
export const redirectLoggedInTo: (redirect: string|any[]) => AuthPipe =
(redirect) => pipe(loggedIn, map(loggedIn => loggedIn && redirect || true));

0 comments on commit fe31191

Please sign in to comment.