CanActivate Depends on Parent Route Resolution

I have a route setup like this:

export const APP_ROUTES: Routes = [ { path: '', resolve: { user: CurrentUserResolver }, children: [ { path: ':sectionKey', canActivate: [SectionAccessGuard], children: [ { path: 'dashboard', component: DashboardComponent } ] } ] } ] 

If the parent route will retrieve the user through an HTTP call, and I want my sub-route :sectionKey activated only if the current user has access to it. The problem is that my canActivate SectionAccessGuard seems to SectionAccessGuard called before the snapshot is full:

 @Injectable() export default class SectionAccessGuard implements CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { console.log(route.data); console.log(route); return true; } } 

In the console, the first entry will have nothing; however, in the 2nd entry, the user field will be populated.

I know that the canActivate method canActivate also return an Observable<boolean> , but I don’t see any bindings on how to wait for the solution to complete.

What am I missing here? I feel it should be pretty straight forward. I am currently using angular v4.0.0-rc.2

+7
angular
source share
3 answers

It has been about 8 months since I posted this, so I’ll talk about where we ended up:

Saving data in the router through resolvers became very inconvenient depending on where the component was located ( this.route.parent.parent.parent.data.user ), so we no longer use resolvers and instead use NgRx to store this information .

Then our guards are responsible for starting the data collection, as well as until they end. Something like that:

 @Injectable() export class AuthenticationGuard implements CanActivate { constructor(private router: Router, private store: Store<ApplicationState>) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { this.store.dispatch(new AuthenticateAction()); return this.store .select('auth') .filter((s) => !!s && !s.authenticating) .map((s) => s.authenticated) .take(1); } } 

If there are a couple of flags in the state (authentication and authentication) that tell the guard where we are in the process.

+1
source share

I'm not sure if the defender can be made to work after recognition is complete, but I will try to move the code from the resolver to canActivate ().

When an observable that receives current user information returns data, use your logic to check if the user is allowed to navigate the route.

0
source share

I am also struggling with this, and I would like to see additional documentation related to this from the Angular team. It seems that canActivate does not wait until it starts, until the parent process ends, but allows.

You can change your code to activate the code in another solution, because the child solution is waiting for parent permission. If it is changed for permission, you will have access to the user through route.parent.data.user, and you can make a call to router.navigate to leave the section if the user has not logged in.

Another approach is to configure a service that can be introduced both in permission protection and in canActivate defender. You will need to set the permissions observed from the protection device and subscribe to it in the canActivate defender.

0
source share

All Articles