Skip to content

Instantly share code, notes, and snippets.

@jasonaden
Last active October 31, 2018 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasonaden/543853aa93b3fb369ad4570a502dcac8 to your computer and use it in GitHub Desktop.
Save jasonaden/543853aa93b3fb369ad4570a502dcac8 to your computer and use it in GitHub Desktop.
Using Guards Redirect
/*
* Guards execute in a similar way to how they used to. However, there is now prioritization involved. A guard
* closest to the root of the application takes priority, such that if guards for child routes return `false`
* or a `UrlTree` but parents haven't resolved yet, we will wait for the parents to resolve first. The highest
* prioirty failure (either `false` or `UrlTree` redirect) will take priority.
*
* If a `UrlTree` is returned from a guard, the current navigation will be cancelled (firing a `NavigationCancel`
* event) and a new navigation will be kicked off to the redirected URL.
*/
// Example AuthGuardService
@Injectable()
export class AuthGuardService implements CanActivate {
constructor(public auth: AuthService, public router: Router) {}
// Notice this can now return UrlTree
canActivate(): Promise<boolean|UrlTree> {
return this.auth.isAuthenticated()
.then(isAuth => isAuth || this.router.parseUrl('/login');
}
}
// Example simple promise based role guard
@Injectable()
export class RoleGuardService implements CanActivate {
constructor(public auth: AuthService, public router: Router) {}
canActivate(route: ActivatedRouteSnapshot): Promise<boolean|UrlTree> {
this.auth.getToken()
.then(token => {
if (this.auth.decode(token).role === route.data.expectedRole) {
return true;
else {
return this.router.parseUrl('/login');
}
});
}
}
// Synchronous guard to check if experiments is enabled in a query param
@Injectable()
export class ExperimentsGuardService implements CanActivate {
constructor(public router: Router) {}
canActivate(route: ActivatedRouteSnapshot, _, redirect): boolean|UrlTree {
if (route.queryParams.exp === 'enabled') {
return true;
} else {
return this.router.createUrlTree(['/error', {message: "Experiments are not enabled"}]);
}
}
}
export const ROUTES: Routes = [
// Entire app is behind the `AuthGuardService`, and re-run on all route changes
{ path: '',
component: HomeComponent,
canActivate: [AuthGuardService],
runGuardsAndResolvers: 'always',
children: [
{ path: 'profile', component: ProfileComponent },
{
path: 'admin',
component: AdminComponent,
canActivate: [RoleGuardService],
data: {
expectedRole: 'admin'
}
},
{
path: 'admin-new',
component: AdminNewComponent,
// Because this guard is in `children` of the parent route, when ExperimentsGuardService
// synchronously returns a UrlTree, it will wait for AuthGuardService of the parent
// route to finish resolving. If AuthGuardService returns `true`, the ExperimentsGuardService
// redirect will be followed. However, if AuthGuardService returns `UrlTree`, the
// ExperimentsGuardService redirect will be ignored and the redirect will be to the return
// of the AuthGuardService.
canActivate: [RoleGuardService, ExperimentsGuardService],
data: {
expectedRole: 'admin'
}
}
]
},
{ path: '**', redirectTo: '' }
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment