我正在尝试阻止普通用户访问应用程序的管理员端。当前,Firestore文档上的admin属性为true或false。如果为false,则在尝试访问主页时应将其重定向到主页,否则允许用户继续访问该页面。
这是我的admin-auth-guard.service.ts
userDoc: AngularFirestoreDocument<User>;
user: Observable<User>;
constructor(private afAuth: AngularFireAuth,
private afs: AngularFirestore,
private router: Router) {}
canActivate() {
this.userDoc = this.afs.doc('users/' + this.afAuth.auth.currentUser.uid);
this.user = this.userDoc.valueChanges();
return this.user.map(role => {
if (role.admin)
return true
this.router.navigate(['/']);
return false;
});
}
我相信代码会起作用,尽管在初始化Admin Auth Guard时,请求发生得太快,并且uid为null。
我收到此错误:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'uid' of null
TypeError: Cannot read property 'uid' of null
Firestore和angular似乎是一个小众话题,两者的信息不多。任何帮助将不胜感激!
答案 0 :(得分:1)
您不能依赖于selected
的同步访问,因为当用户(内部)通过身份验证时,firebase将填充它。我宁愿将其视为可观察并异步访问。
因此,让它变得可观察,创建一个uid
文件:
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()
将发出一个项目。定义此项目后(从而对用户进行身份验证),将向firestore发出请求以检索用户文档。当authState
未定义(因此用户未通过身份验证)时,将发出authState
,这意味着将不返回任何内容,并且可观察项也不会终止。
现在在您的身份验证防护中使用此类:
NEVER
我们将复杂性保留在auth服务内部,结果,auth防护变得很笨。它订阅@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),
);
}
}
并在用户未定义(未验证)或不是管理员时重定向到登录。