Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a base guard for all routes in Angular 2 application

Is there a way to set a "base" canActivate when configuring routes in Angular2? So that all routes are covered by the same base check, and then each route can have a more granular check.

I have an AppModule with routing like this:

@NgModule({
    imports: [
        RouterModule.forRoot([
            {
                path: '',
                component: HomeComponent,
                canActivate: [AuthenticationGuardService],
                data: { roles: [Roles.User] }
            }
        ])
    ],
    exports: [
        RouterModule
    ]
})
export class AppRoutingModule { }

And for the feature module FeatureModule:

@NgModule({
    imports: [
        RouterModule.forChild([
            {
                path: "feature",
                component: FeatureComponent,

                // I'd like to avoid having to do this:
                canActivate: [AuthenticationGuardService],
                data: { roles: [Roles.User] }
            }
        ])
    ],
    exports: [
        RouterModule
    ]
})
export class FeatureRoutingModule { }

I let AuthenticationGuardService check if a user has access to a route by using the roles provided in data.

Can I do something to avoid having to set canActivate and data in all my feature routing modules? I'd like to just configure a "base" canActivate for all routes in this application.

like image 512
Joel Avatar asked Nov 10 '16 09:11

Joel


People also ask

Can we use multiple guards in Angular?

We can use multiple route guards and then the route will only be accessible when all route guards return true. That's it!

What are route guards in Angular 2?

Angular's route guards are interfaces which can tell the router whether or not it should allow navigation to a requested route. They make this decision by looking for a true or false return value from a class which implements the given guard interface.


2 Answers

I've written a solution to add the Guard dynamically for every routes of my app (including those defined by child modules).

I've figured out this solution while reading this Router Docs.

Edit

Here is a living StackBlitz sample.

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'login', component: LoginComponent, data: { skipGuard: true } },
  { path: '403', component: ForbiddenComponent, data: { skipGuard: true } },
  { path: '**', component: NotFoundComponent, data: { skipGuard: true } }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: []
})
export class AppRoutingModule {
  
  constructor(router: Router) {
    router.config
        .filter(route => !route.data || !route.data.skipGuard)
        .forEach(route => this.addGuard(route));
  }
  
  private addGuard(route: Route): void {
    route.canActivate = route.canActivate ? 
                   [AuthGuard].concat(route.canActivate) : [AuthGuard];
    route.canActivateChild = route.canActivate ? 
                   [AuthGuard].concat(route.canActivate) : [AuthGuard];
  }
}
like image 200
Jorge Ciombalo Avatar answered Sep 22 '22 23:09

Jorge Ciombalo


const routes: Routes = [
  {
    path: '',
    canActivate: [AuthGuard],
    children: [
      { path: '', component: HomeComponent },
      { path: 'builds', component: BuildsComponent },
      { path: 'files', component: FilesComponent },
      { path: 'publications', component: PublicationsComponent }
    ]
  },
  { path: 'login', component: LoginComponent },
  { path: '**', redirectTo: '' }
];
like image 25
Jeroen Zwartepoorte Avatar answered Sep 23 '22 23:09

Jeroen Zwartepoorte