Using BehaviorSubject in auth-guard's canActivate

你说的曾经没有我的故事 提交于 2019-12-03 03:59:01

Guard's canActivate method, as its name suggests, resolves upon the attemption to activate specific route.

As I understand from the code provided, you're trying to redirect user to the /user route upon retrieving auth uid from the server. To achieve that, you need to initiate redirecting to the desired route once the auth uid is retrieved - e.g. after logging in, and let your guard do its job, enable or deny the access to the route.

After sorting things out, here is the walk-through the changed code and structure:

AuthInfo class:

// No changes.

AuthService:

@Injectable()
export class AuthService {

  static UNKNOWN_USER = new AuthInfo(null);
  authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);

  constructor(private af: AngularFire) { }

  logIn(email: string, password: string): Promise<FirebaseAuthState> {
    return this.af.auth.login({email: email, password: password});
  }

  getAuthInfo(): Observable<AuthInfo> {
    return this.af.auth.map(auth => {
      if(auth) {
        console.log('got the uid');
        let authInfo = new AuthInfo(auth.uid);
        this.authInfo$.next(authInfo);
        return authInfo;
      } 
      else {
        this.authInfo$.next(AuthService.UNKNOWN_USER);
        return AuthService.UNKNOWN_USER;
      }
    });
  }
}

AuthGuard:

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService,
              private router: Router) {
  }

  canActivate(): Observable<boolean> | boolean {

    // get the most recent value BehaviorSubject holds
    if (this.authService.authInfo$.getValue().isLoggedIn()) {
      // can access targeted route
      return true;
    }

    /*
    User is not logged in as stored authInfo indicates, 
    but in case the page has been reloaded, the stored value is lost, 
    and in order to get real auth status we will perform the server call,
    (authService.getAuthInfo method will automatically update the BehaviorSubject value, 
    and next time the protected route is accessed, no additional call will be made - until 
    the next reloading).
    */

    return this.authService.getAuthInfo()
        .map((authInfo: AuthInfo) => {
          if(authInfo.isLoggedIn()) {
            // can access targeted route
            return true;
          }

          this.router.navigate(['login']); // redirect to login screen
          return false;
        });
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!