简体   繁体   English

Angular AuthGuard canActivate with observable from Promise 不工作

[英]Angular AuthGuard canActivate with observable from promise not working

I'm trying to guard the admin panel in Angular so that only admin users can access it.我正在尝试保护 Angular 中的管理面板,以便只有管理员用户才能访问它。 While creating the admin AuthGuard I ran into a problem where the AuthGuard doesn't seem to work when the logic is a little bit more complex than just "is the user logged in?".在创建管理员 AuthGuard 时,我遇到了一个问题,当逻辑比“用户是否登录?”稍微复杂一点时,AuthGuard 似乎不起作用。

Instead of the expected redirect I get an empty white screen.我得到一个空的白色屏幕,而不是预期的重定向。

I've been banging my head agains the wall for the past couple of hours trying to find the root cause and it seems to get stuck at this line: const user = await this.firebaseAuth.user.toPromise();在过去的几个小时里,我一直在努力寻找根本原因,但它似乎卡在了这一行: const user = await this.firebaseAuth.user.toPromise(); but I don't understand why.但我不明白为什么。

Can someone guide me in the right direction because I seem to be lost in the jungle of Angular and Observables?有人能指引我走向正确的方向,因为我似乎迷失在 Angular 和 Observables 的丛林中吗?

The AuthGuard canActivate method: AuthGuard canActivate 方法:

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    return this.accountDataService.userIsAdmin().pipe(
      take(1),
      map((admin) => {
        console.log(admin);

        if (admin) {
          return true;
        }

        this.router.navigate(['/aanmelden']);
        return false;
      })
    );
  }

This is the dataService:这是数据服务:

userIsAdmin(): Observable<boolean> {
    return from(
      new Promise<boolean>(async (resolve) => {
        const user = await this.firebaseAuth.user.toPromise();

        if (user === undefined) {
          resolve(false);
        }

        const result = await user.getIdTokenResult();
        const admin = result.claims.admin;

        if (admin === undefined || admin === null || admin === false) {
          resolve(false);
        }

        resolve(true);
      })
    );
  }

I guess this.firebaseAuth.user doesn't complete.我猜this.firebaseAuth.user没有完成。 toPromise only resolves when the observable completes. toPromise仅在 observable 完成时解析。

You should rewrite your userIsAdmin function to only use observables.您应该重写userIsAdmin函数以仅使用 observable。

userIsAdmin(): Observable<boolean> {
  return this.firebaseAuth.user.pipe(
    switchMap(user => {
      if (user === undefined || user === null) {
        return of(false);
      }

      return from(user.getIdTokenResult()).pipe(
        map(result => {
          const admin = result.claims.admin;

          if (admin === undefined || admin === null || admin === false) {
            return false;
          }

          return true;
        })
      )
    })
  );
}

The observable needs to complete. observable 需要完成。 I had more success with .take(1) at the end.最后我在.take(1)上取得了更大的成功。 That would explain why Observable.of(true) worked.这将解释为什么Observable.of(true)起作用。 Try this:尝试这个:

canActivate(): Observable<boolean> {
  return this.auth.map(authState => {
    if (!authState) this.router.navigate(['/aanmelden']);
    console.log('activate?', !!authState);
    return !!authState;
  }).take(1)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM