我一直花费数小时的时间在圈子里努力解决这个问题。我需要根据用户角色保护路由。
constructor(private af: AngularFire, private db: AngularFireDatabase, private router: Router, private auth: AngularFireAuth) {
af.auth.subscribe(user => {
if (user) {
this.getUserRole(user);
} else {
console.log('no user');
}
});
}
这至少得到了这个角色:
getUserRole(user): any {
this.db.list('users', {
query: {
orderByKey: true,
equalTo: user.uid
}
}).subscribe(user => console.log(user[0].role));
}
这是一个有效的CanActivate,基于此用户是否已登录,但显然角色无关紧要。
canActivate(route:ActivatedRouteSnapshot,
state:RouterStateSnapshot):Observable<boolean> {
return this.af.auth.take(1)
.map(authSate => !!authSate)
.do( authenticated => {
console.log(authenticated)
if (!authenticated)
this.router.navigate(['/login'])
})
}
我无法弄清楚如何将用户角色带入帐户。我的设置非常基础...它/ users / $ uid / role。
这是我尝试过的其他内容:
导出类AuthService {
static UNKNOWN_USER = new AuthInfo(null, null);
authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);
constructor(private af: AngularFire, private db: AngularFireDatabase, private router: Router, private auth: AngularFireAuth) {
af.auth.subscribe(user => {
if (user) {
let getRole = this.db.list('users', {
query: {
orderByKey: true,
equalTo: user.uid
}
}).subscribe(snap => {
if (snap.length === 0) {
return;
} else {
let role = "";
role = snap[0].role
const authInfo = new AuthInfo(user.uid, role);
this.authInfo$.next(authInfo);
}
});
} else {
console.log('no user');
}
});
}
这是AuthInfo类:
导出类AuthInfo {
constructor(public $uid: string, public role: string) { }
isLoggedIn() {
console.log('from authinfo', !!this.$uid)
//tells us if user is logged in or not
return !!this.$uid;
}
isGroupALoggedIn() {
//tells us if user is logged in or not
return !!this.$uid && this.role === "GroupA";
}
isGroupBLoggedIn() {
//tells us if user is logged in or not
return !!this.$uid && this.role === "GroupB";
}
}
这是来自主页组件的测试:
导出类HomeComponent实现OnInit {
authInfo: AuthInfo
constructor(private authService: AuthService) { }
ngOnInit() {
//returns boolean
this.authService.authInfo$.subscribe(authInfo => {
console.log(authInfo);
this.authInfo = authInfo
});
}
}
这也有效但我无法弄清楚如何将其与CanActivate
联系起来答案 0 :(得分:2)
您需要使用mergeMap()
运算符链接两个可观察对象 - 获取用户的角色和获得用户角色的角色。
将所有这些代码放在canActivate
挂钩中。
canActivate(): Observable<boolean> {
return af.auth
.mergeMap(user =>
// Extract the role from userData if user exists, or empty string if no user.
user ? getUserRole(user).map(userData => userData[0].role) : Observable.of('')
)
// Transform the role into true or false
// since this is what canActivate() must return.
.map({
if (userRole === "GroupA") {
return true;
} else {
this.router.navigate(['/login']);
}
});
}
在此示例中,将为具有角色&#34; GroupA&#34;的用户激活路线。
更新:根据dhndeveloper要求,检查是否存在用户+重定向(如果没有允许的角色)。
答案 1 :(得分:0)
除了@ AngularFrance的解决方案之外,还需要检查用户是否存在:
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.af.auth
.mergeMap(user => {
if (user) {
// Extract the role from userData
return this.authService.getUserRole(user).map(userData => userData[0].role)
} else {
return Observable.of({});
}
})
// Transform the role into true or false
// since this is what canActivate() must return.
.map(userRole => {
if (userRole === "GroupA") {
return true;
} else {
this.router.navigate(['/login']);
}
});
}