Вы не можете полагаться на инициализацию uid
при синхронном доступе к нему, потому что он будет заполнен firebase, когда пользователь (внутренне) аутентифицирован. Я предпочел бы рассматривать это как наблюдаемое и обращаться к нему асинхронно.
Итак, давайте сделаем это видимым, создадим auth.service.ts
файл:
Injectable()
export class FirebaseAuthService {
constructor(
private angularFireAuth: AngularFireAuth,
private angularFirestore: AngularFirestore,
) {
}
getUser(): Observable<any> {
return this.angularFireAuth.authState.pipe(
mergeMap(authState => {
if (authState) {
return from(this.angularFirestore.doc(`users/${authState.uid}`).get());
} else {
return NEVER;
}
})
);
}
// is logged in?
// signin
// more auth related methods
}
Так что можно подписаться на getUser()
. Всякий раз, когда изменяется глобальное состояние аутентификации, authState
будет испускать элемент. Когда этот элемент определен (таким образом, пользователь проходит проверку подлинности), будет сделан запрос в firestore, чтобы получить документ пользователя. Когда authState
не определен (таким образом, пользователь не аутентифицирован), будет выдан NEVER
, что означает, что ничего не будет возвращено и наблюдаемое не будет прекращено.
Теперь используйте этот класс в вашей охране:
@Injectable()
export class AdminAuthGuardService implements CanActivate {
constructor(
private router: Router,
private firebaseAuthService: FirebaseAuthService,
) {
}
canActivate() {
return this.firebaseAuthService.getUser().pipe(
map(user => {
if (!user || !user.admin) {
// noinspection JSIgnoredPromiseFromCall
this.router.navigate(['/login']);
return false;
}
return true;
}),
take(1),
);
}
}
Мы сохраняем сложность внутри службы аутентификации, и, как следствие, аутентификация аутентификации становится довольно глупой. Он подписывается на getUser
и перенаправляет на вход в систему, когда пользователь не определен (не аутентифицирован) или не является администратором.