younes sofiane
younes sofiane

Reputation: 451

Go to a route if at least one guard is active

The guards in Angular2 routing run in the order they are provided. But in the case of guards with observables, even if the first guard is true, angular ignores it, and only apply the result from the second guard's observable.

How can I solve this?

const mainRoutes: Routes = [
  {
  path: 'app',
  component:MainComponent,
  canActivate:[AuthGuard],
  children:[
     { path: 'dashboard',  component: DashboardComponent },
     { path: 'protectedRoute',  component: ProtectedRouteComponent, canActivate:[Admin1Guard,Admin2Guard] }
  ]}
];

The first guard:

canActivate() :Observable<boolean>{
    return this.authService.getUser().map(res=>{
        if(res.user.role=="admin1")
          return true;
      }).take(1);
   }
 }

The second guard:

canActivate() :Observable<boolean>{
    return this.authService.getUser().map(res=>{
        if(res.user.role=="admin2")
          return true;
      }).take(1);
    }
  }

Upvotes: 0

Views: 1363

Answers (1)

AngularChef
AngularChef

Reputation: 14077

I would refactor the role-checking logic into a single, generic CheckRoleGuard service and attach the name of the role to check to the route via the data property:

{
  path: 'protectedRoute1',
  component: SomeComponent,
  canActivate: [CheckRoleGuard],
  data: { allowedRoles: ['admin','editor'] }
},
{
  path: 'protectedRoute2',
  component: SomeComponent,
  canActivate: [CheckRoleGuard],
  data: { allowedRoles: ['admin'] }
}

And now for the the RoleGuard service:

@Injectable()
class CheckRoleGuard {

  constructor(private authService: AuthService) { }

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    // Retrieve the allowed roles from `route.data`.
    const allowedRoles = route.data['allowedRoles'];

    return this.authService.getUser()
      .map(data => {
        return allowedRoles.indexOf(data.user.role) !== -1;
      });
  }

}

Upvotes: 2

Related Questions