Combining ngxs and rxjs to create an route guard

640 Views Asked by At

Bare with me since I'm quite new to RXJS and NGXS. I am trying to setup an authguard using both libraries.

So to start with:

./AuthState.ts

@Injectable()
export class AuthState {

  @Selector()
  static isAuthenticated(state: AuthStateModel): boolean {
    return !!state.token;
  }

  @Action(Login)
  login(ctx: StateContext<AuthStateModel>, action: Login) {
    return this.authService.login(action.payload).pipe(
      tap((result: { token: string }) => {
        ctx.patchState({
          token: result.token,
          username: action.payload.username
        });
      })
    );
  }

  // ... left out for brevity

Now I've seen a few examples of observables being used, using a .take(1) method. In the NXJS documentation it states that the store select has a function named selectOnce. Which basically does select().pipe(take(1)).

How can I put that into practice?

./auth.guard.ts

canActivate(_, state: RouterStateSnapshot) {

    // I'd like to do an early return when the user is not authenticated
    // And I was assuming since the `isAuthenticated` method in AuthState returns a boolean this would work... (but it doesn't)
    if (!this.store.selectOnce((authState) => authState.isAuthenticated)) {
      this.router.navigate(
        ['auth/login'],
        { queryParams: { returnUrl: state.url } }
      );
      return false;
    }

    // otherwise all is good...
    return true;   
  }

But that is not working. So I am probably getting one of the concepts wrong.

1

There are 1 best solutions below

0
On BEST ANSWER

Oké. I had it a bit backwards:

  canActivate(_, state: RouterStateSnapshot) {
    const isAuthenticated = this.store.selectSnapshot(AuthState.isAuthenticated);
    if (!isAuthenticated) {
      this.router.navigate(['auth/login'], { queryParams: { returnUrl: state.url } });
      return false;
    }
    return true;
  }

Turns out you should just get the property isAuthenticated from the class AuthState using selectSnapshot. (As was clearly described in the documentation)

See also snapshot selects.