Reputation: 111
We have a Router Guard which checks if a user is logged in and admin It should also check if a request we send to a server is has the right result.
The problem is the canActivate function is finished before the server request is finished, so the Router Guard is always false.
I hope you have a solution for this problem
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
var user = JSON.parse(localStorage.getItem('currentUser'));
if (user != null&&!user.isNotAdmin) {
if(this.userService.isLoggedIn(user)){
return true;
}else{
return false;
}
}else{
// not logged in so redirect to login page with the return url
this.router.navigate([''], { queryParams: { returnUrl: state.url } });
return false;
}
Upvotes: 8
Views: 7312
Reputation: 14900
Later versions of Angular can return an Observable
from the canActivate
method, making this much easier. If the user is not found in localStorage
you return immediately, if a user is found however you call your service method. The pipe
and tap
is used to intercept it so to speak, and if it returns false
it also navigates to ''
.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<any> {
const user = JSON.parse(localStorage.getItem('currentUser'));
if (user === null || user.isNotAdmin) {
return false;
}
return this.userService.isLoggedIn(user).pipe(
tap((isLoggedIn) => {
if (!isLoggedIn) {
this.router.navigate([''], { queryParams: { returnUrl: state.url } });
}
})
}
}
PS: Checking for admin status from localStorage
is not very secure, but of course depends on your project whether it is acceptable risk.
Upvotes: 0
Reputation: 110
You have to use async/await
to ensure canActivate waits till the resolution of your server request. Here's some sample code to help you:
/* UserService */
isLoggedIn(user): Observable<boolean> {
// check if user is logged in
return isUserLoggedIn;
}
/* Guard */
async canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Promise<boolean> {
const user = JSON.parse(localStorage.getItem('currentUser'));
if (user !== null && !user.isNotAdmin) {
const isUserLoggedIn: boolean = await this.userService.isLoggedIn(user).toPromise();
// toPromise() converts Observable to Promise (async/await only works on Promises)
// the code 'waits' at the above line till the server request is resolved
return isUserLoggedIn;
} else {
// not logged in so redirect to login page with the return url
this.router.navigate([''], { queryParams: { returnUrl: state.url } });
return false;
}
References if you want to read further:
Upvotes: 4