1
votes

I am using the canActivate method in a guard. Inside I have an observable, which gives me back an object. This object has a password. I check the password, and if it's right, I want canActivate to return true, if not, false.

Here is the code

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const uid = route.params.userId;
    const hackId = route.params.hackId;
    const token = this.authService.token;
    const queryParamsPassword = route.queryParams.password;
    this.hacksStorageService.fetchHack(token, uid, hackId)
      .subscribe(
        hack => {
          const hackPassword = hack[0].password;
          if (queryParamsPassword === hackPassword ) {
            return true
          } else {
            this.router.navigate(["/"]);
            return false
          }
        },
        error => {
          return false;
        }
      )
  }

I having trouble in understanding the response. I have to give the response whenever it's done. Once I get the value from the subscription, then I want to return the boolean in the canActivate.

The error that I get is on the canActivate method (in red)

[ts]
Property 'canActivate' in type 'RoleGuard' is not assignable to the same property in base type 'CanActivate'.
  Type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => void' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable<boolean> | Pr...'.
    Type 'void' is not assignable to type 'boolean | Observable<boolean> | Promise<boolean>'.

I thought I am returning in every branch of the if, so it should be enough, but apparently not. If I return the subscription, he also complains.

Any help? Thanks a lot.

1
No, you're retuning within the subscribe callback, which is not the same as returning from canActivate. Which version of RXJS are you using?user184994

1 Answers

2
votes

Your method must return something. It doesn't return anything.

It can return a boolean. That is only possible if you can know the value to return synchronously. But you need an asynchronous call to know what the result should be. So you can't return a boolean. And that's why a guard can also return an Observable<boolean>. So, do that:

return this.hacksStorageService.fetchHack(token, uid, hackId).pipe(
  map(hack => {
    const hackPassword = hack[0].password;
    if (queryParamsPassword === hackPassword ) {
      return true;
    } else {
      this.router.navigate(["/"]);
      return false;
    }
  })
);