【发布时间】:2021-10-25 11:31:43
【问题描述】:
我正在尝试做一个“AdminGuard”,这应该基于两件事:
- 用户是否登录?
- 用户是否有管理员权限?
我有一个AuthService,它提供两个Observable。
我做了以下事情:
@Injectable({
providedIn: 'root'
})
export class IsAdminGuard implements CanActivate {
constructor(private auth: AuthService, private router: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> {
console.log(this.auth)
return combineLatest([this.auth.isLoggedIn, this.auth.isAdmin]).pipe(
take(1),
map((authInfo) => {
console.log(authInfo)
if (!authInfo[0]) {
console.error('Access denied - Unauthorized')
return this.router.parseUrl('/auth/');
} else if (!authInfo[1]) {
console.error('Access denied - Admin only')
return this.router.parseUrl('/auth/unauthorized');
} else {
return true;
}
})
);
}
}
console.log(this.auth) 被调用并且似乎具有有效值,但第二个 console.log 从未被调用并且我的组件未加载。
如果我从路线中移除警卫:
{
path: 'admin',
component: AdminComponent,
//canActivate: [IsAdminGuard],
}
它有效,所以我很确定是 IsAdminGuard 不起作用。
我还根据相同的布尔值显示其他一些东西(一些 *ngIf="authService.IsLoggedIn | async" 正在工作,所以我真的不明白我搞砸了什么?
编辑 以下是我如何在我的 AuthService 中更新 IsLoggedIn/IsAdmin/IsUser 的不同值:
constructor(public afAuth: AngularFireAuth, public router: Router, private afStore: AngularFirestore) {
this.afAuth.authState.subscribe(async user => {
console.log('handling auth')
if (this._roleSubscription) {
this._roleSubscription.unsubscribe();
this._roleSubscription = undefined;
}
if (user) {
this._user.next(user);
this._isLoggedIn.next(true);
this._roleSubscription = this.afStore.doc<Roles>(`roles/${user.uid}`).valueChanges().subscribe(role => {
console.log('updating roles', role)
if (role) {
this._isAdmin.next(role.admin == true)
this._isUser.next(role.admin == true || role.user == true);//Admin have also an heart, they are users too!
} else {
this._isAdmin.next(false);
this._isUser.next(false);
}
});
} else {
this._user.next(undefined);
this._isLoggedIn.next(false);
this._isAdmin.next(false);
this._isUser.next(false);
await this.router.navigate(['/auth']);
}
console.log('values updated')
})
}
【问题讨论】:
-
你能展示一下 observables 的
AuthService实现吗?Observables何时被输入值?你的警卫很可能在此之前运行,你应该将AuthService逻辑移动到APP_INITIALIZER -
combineLatest的所有源 Observables 必须至少发射一次,这是我首先要看的地方。 -
@Eldar 我不这么认为,因为我没有看到
console.log(authInfo),所以并不是我错过了更新,我只是从来没有得到任何价值 -
如果你想在两个 observable 都发出一个值后发出一次,也许可以尝试使用
forkJoin而不是combineLatest? -
@PoulKruijt 我添加了我的服务的更新部分
标签: angular rxjs guard angular2-observables