Angular 8-保护管理路由,无法从Firebase获取Uid

时间:2019-10-03 06:09:07

标签: angular firebase firebase-realtime-database

我使用angular 8,Firebase 6.6.2和rxjs 6.4.0。由于我使用的是最新版本的rxjs,因此我在管道内使用了switchMap。但是我在响应中遇到以下错误。

  

类型'(user:User)=> AngularFireObject '的参数不是   可分配给类型'(值:用户,索引:数字)=>的参数   ObservableInput '。

     

类型'AngularFireObject '无法分配给类型   'ObservableInput '。

     

类型中缺少属性“ [Symbol.iterator]”   “ AngularFireObject ”,但类型为“ Iterable ”是必需的。

这是我的代码:

user.service.ts

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

app-user.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();
  }
}

数据库:

enter image description here

3 个答案:

答案 0 :(得分: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.ts重命名为admin-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]
  }
])

答案 1 :(得分:0)

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

admin-auth.service.ts

canActivate() {
    return this.auth.user$.pipe(map(user => {
      if (user.isAdmin) {
        return true;
      }
      return false;
    }));

答案 2 :(得分:0)

Activate必须返回什么? Observable,对吧?

我们还能返回什么? AngularFireObject,这不是可观察的。

因此,在 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