0

I know there are several threads and I literally tried every solution and I'm not sure where's the difference to my situation.

I want to create a Guard to access the view to change a password after a token was validated by the server.

   canActivate(
     route: ActivatedRouteSnapshot,
     router: RouterStateSnapshot
   ):
     | Observable<boolean | UrlTree>
     | Promise<boolean | UrlTree>
     | boolean
     | UrlTree {
     const queryString = window.location.search;
     const urlParams = new URLSearchParams(queryString);
     if (urlParams.has("token")) {
       let token = urlParams.get("token");
       this.authService.getResetPasswordPermission(token).subscribe(
         (res) => {
           return true;
         },
         (err) => {
           return false;
         }
       );
     } else {
       return this.router.createUrlTree(["/authenticate"]);
     }
   }

I know that subscribe won't wait for the result and so just return this.router.createUrlTree(["/authenticate"]); gets executed. I've tried to use map and pipe but then it does never go into the result of the method, so neither res or err.

And somehow I will always be redirected to localhost:4200 instead of localhost:4200/changePassword where I want to go or even localhost:4200/authenticate where I should land else.

The Observable method that talks to the server looks like this:

   getResetPasswordPermission(token): Observable<any> {
     let data = { token: token };
     return this.http.get<any>(RESET_PASSWORD_PERMISSION_API, { params: data });
   }

If it succeeds the answer is a ResponseEntity.ok(token).

If not ResponseEntity.badRequest(). I know they are both not syntactical correct but you get what I mean.

The token is needed again to send it with the change request if I would land on the changePassword page.

CptDayDreamer
  • 1,526
  • 6
  • 25
  • 61

1 Answers1

3

I know you tried already but I think that the map operator fits your case. Try something like this:

canActivate(
     route: ActivatedRouteSnapshot,
     router: RouterStateSnapshot
   ):
     | Observable<boolean | UrlTree>
     | Promise<boolean | UrlTree>
     | boolean
     | UrlTree {
     const queryString = window.location.search;
     const urlParams = new URLSearchParams(queryString);
     if (urlParams.has("token")) {
       let token = urlParams.get("token");
       return this.authService.getResetPasswordPermission(token).pipe(
          catchError(err => return of(null)),
          map(resp => !!resp)
       );
     } else {
       return this.router.createUrlTree(["/authenticate"]);
     }
   }
  • Give me a second I try again but I think it won't help either – CptDayDreamer Jul 08 '20 at 13:54
  • Okay actually works. At least for the case the token is valid. To understand it, where is the difference to this here: https://stackoverflow.com/a/50143721/10565504 ? You are missing curly brackets between return of(null). If the error is caught now I have to scenario I described in my question that I just land on localhost:4200 instead of /authenticate and tried to change it but it does not work – CptDayDreamer Jul 08 '20 at 14:07
  • There's no difference, the problem with you code was that you were subscribing to the getResetPasswordPermission function inside the canActivate function and you were trying to return a simple boolean in the result function. The map operator returns an observable with the mapped value inside of it. To achive the behaviour for the token not valid you can use ``` catchError((err) => { this.router.navigate(['/login']); return of(false); }) ``` of the answer you linked – Edoardo Pacciani Jul 08 '20 at 14:45