This.router.navigate in Guard blocks routes in the future

I installed two defenders in Angular 4 - one that redirects users to the login page when they try to get to the secure route, and one that redirects users to the welcome page from Home.

The guards themselves work great ... but I noticed a very strange behavior. Adding redirection through this.router.navigateto GuardTraveler protects the application in a state where I cannot access protected routes from the first guard even after logging in. I just keep getting sent to the homepage.

Here are my guards:

export class AuthGuardLoggedInUser implements CanActivate {
  private isLoggedIn: boolean;
  private working: boolean;
  constructor (@Inject(Store) private _store:Store<AppStore>, @Inject(Router) private _router: Router) 
  {
    _store.select(state => state.AuthNState).subscribe(auth =>
    {
      this.isLoggedIn = auth.connected
      this.working = auth.working
    })
  }
  canActivate() {
    if (this.working)
    {
      let promise: Promise<boolean>  = new Promise((resolve, reject) => {
        let sub = this._store.select(state => state.AuthNState).subscribe(auth =>
        {
          if (!auth.working) {
            resolve(auth.connected)
            sub.unsubscribe()
            if (!auth.connected) this._router.navigate(['/i/login']);
          }
        })
      });
      return promise
    }
    else if (this.isLoggedIn){
      return true
    }
    else {
      this._router.navigate(['/i/login']);
    }

export class WelcomeTraveler implements CanActivate {
  private hasAlreadyVisitedWelcomePage: boolean;
  private isLoggedIn: boolean;
  private working: boolean;
  constructor (@Inject(Store) private _store:Store<AppStore>, @Inject(Router) private _router: Router) 
  {
    _store.select(state => state.AuthNState).subscribe(auth =>
    {
      this.isLoggedIn = auth.connected
      this.working = auth.working
    })
  }
  canActivate() {
    if (this.working)
    {
      let promise: Promise<boolean> = new Promise((resolve, reject) => {
        let sub = this._store.select(state => state.AuthNState).subscribe(auth =>
        {
          if (!auth.working) {
            resolve(auth.connected)
            sub.unsubscribe()
            this.hasAlreadyVisitedWelcomePage = true
            this._router.navigate(['/i/welcome']);
          }
        })
      });
      return promise
    }
    else if (this.isLoggedIn){
      return true
    }
    else if (!this.hasAlreadyVisitedWelcomePage){
      this.hasAlreadyVisitedWelcomePage = true
      this._router.navigate(['/i/welcome']);
    }
    else return true
  }
}

And here is a fragment of the routing table:

export var AppRoutes = RouterModule.forRoot([
  {
    path: '',
    component: HomeComponent,
    canActivate: [WelcomeTraveler]
  }, {
    path: 'i/getstarted',
    component: GetStartedPageComponent,
    canActivate: [AuthGuardLoggedInUser]
  }, {
    path: 'i/login',
    component: LoginPageComponent
  }, {
    path: 'i/profile',
    component: ProfilePageComponent,
    canActivate: [AuthGuardLoggedInUser]
  }, {
    path: 'i/welcome',
    component: WelcomePageComponent
  }])

this.router.navigate WelcomeTraveler, , , ! "" ( ). , .

?

+4
1

, . , , , , router.navigate - /... , , , , .

:

export class LoginPageComponent implements OnDestroy {
   private _redirectSubscription: Subscription;
   constructor (private _store:Store<AppStore>, private router: Router) {
      this._redirectSubscription = _store.select((state) => state.AuthNState).subscribe((auth) =>
      {
        if (auth.connected) this.router.navigate(['']);
      })
   }

   ngOnDestroy() {
     //Called once, before the instance is destroyed.
     //Add 'implements OnDestroy' to the class.
     this._redirectSubscription.unsubscribe();
   }
}
+1

Source: https://habr.com/ru/post/1686580/


All Articles