2

我使用 Angular 8、Firebase 6.6.2 和 rxjs 6.4.0。由于我使用的是 rxjs 最新版本,因此我在管道内使用了 switchMap。但我在回复中收到以下错误。

'(user: User) => AngularFireObject<AppUser>' 类型的参数不能分配给'(value: User, index: number) => ObservableInput<any>' 类型的参数。

类型“AngularFireObject<AppUser>”不可分配给类型“ObservableInput<any>”。

“AngularFireObject<AppUser>”类型中缺少属性“[Symbol.iterator]”,但在“Iterable<any>”类型中是必需的。

这是我的代码:

用户服务.ts

get(uid: string): AngularFireObject<AppUser> {
    return this.db.object('/users/' + uid);
}

应用程序用户.ts

export interface AppUser {
    name: string;
    email: string;
    isAdmin: boolean;
}

admin-auth.service.ts

export class AdminAuthService implements CanActivate {

constructor(private auth: AuthService, private userService: UserService) { }

    canActivate(): Observable<boolean> {
        return this.auth.user$
        .pipe(switchMap(user=> {
        return this.userService.get(user.uid);
    }));
}

auth.service.ts

export class AuthService {
  user$: Observable<firebase.User>;
  constructor(private afAuth: AngularFireAuth, private route: ActivatedRoute) {
    this.user$ = afAuth.authState;
   }

  gLogin() {
    const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
    localStorage.setItem('returnUrl', returnUrl);

    this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  }

  gLogout() {
    this.afAuth.auth.signOut();
  }
}

数据库:

在此处输入图像描述

4

3 回答 3

1

您没有在您的用户中获得用户auth.service.ts

export class AuthService {
    user$: Observable<firebase.User>;

    constructor(private afAuth: AngularFireAuth, 
              private route: ActivatedRoute,
              private userService: UserService) {
        this.user$ = afAuth.authState;
    }

    // The code omitted for the brevity

    public getappUser(): Observable<AppUser> {
      return this.user$
         .pipe(
              switchMap(user => {          
                  if (user) { 
                       return this.userService.get(user.uid).valueChanges(); 
                  }
                  return of(null);
              }));
    }      
}

此外,您需要重命名admin-auth.service.tsadmin-auth-guard.service.ts

import { tap, map } from 'rxjs/operators';

export class AdminAuthGuard implements CanActivate {


  constructor(private auth: AuthService,
              private userService: UserService) { }

  canActivate(): Observable<boolean> {
    return this.auth.getappUser()
      .pipe(
          tap(val => console.log(`BEFORE MAP: ${val}`)),
          map(x => x.isAdmin)
      );
  }
}

然后您可以使用以下方法保护您的路线AdminAuthGuard

import { AdminAuthGuard } from '...';

RouterModule.forChild([
  { path: 'heroes',
    component: HeroesComponent,
    canActivate: [AdminAuthGuard]
  }
])
于 2019-10-03T11:25:08.023 回答
0

canActivate 必须返回什么?一个Observable,对吧?

我们返回什么?不是AngularFireObjectObservable 的。

因此,在user.service.ts文件中,使用valueChanges()将返回Observable.

get(uid: string): Observable<AppUser> {
  return this.db.object<AppUser>('/users/' + uid).valueChanges();
}

admin-auth-guard.service.ts文件中,

canActivate(): Observable<boolean> {
  return this.afService.user$.pipe(
    switchMap(({uid}) => this.userService.get(uid)),
    map(user => user.isAdmin)
  );
}

为了更好地理解: https ://forum.codewithmosh.com/d/1210-oshop-protecting-admin-routes-not-able-to-get-uid-from-firebase/20

于 2019-10-09T10:25:11.677 回答
0

如果您只想保存管理员路由,只需读取登录用户,如果登录用户是管理员,则 isAdmin 为 true,然后根据此返回 true 或 false。

admin-auth.service.ts

canActivate() {
    return this.auth.user$.pipe(map(user => {
      if (user.isAdmin) {
        return true;
      }
      return false;
    }));
于 2019-10-03T09:08:08.220 回答