Angular 8 - Защита административных маршрутов, не удается получить Uid от Firebase - PullRequest
2 голосов
/ 03 октября 2019

Я использую Angular 8, Firebase 6.6.2 & rxjs 6.4.0. Так как я использую последнюю версию rxjs, я использовал switchMap внутри трубы. Но я получил следующую ошибку в ответе:

Аргумент типа '(пользователь: пользователь) => 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 ]

1 голос
/ 03 октября 2019

Вы не получаете пользователя в своем 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]
  }
])
0 голосов
/ 09 октября 2019

Что должно активировать возврат? 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

0 голосов
/ 03 октября 2019

Если вы хотите сохранить только маршрут администратора, просто прочитайте пользователей, которые вошли в систему. Если пользователь, вошедший в систему, является администратором, то isAdmin имеет значение true, а затем возвращает значение true или false на основании этого.

admin-auth.service.ts

canActivate() {
    return this.auth.user$.pipe(map(user => {
      if (user.isAdmin) {
        return true;
      }
      return false;
    }));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...