我使用angular 8,Firebase 6.6.2和rxjs 6.4.0。由于我使用的是最新版本的rxjs,因此我在管道内使用了switchMap。但是我在响应中遇到以下错误。
类型'(user:User)=> 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();
}
}
数据库:
答案 0 :(得分:1)
您没有在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]
}
])
答案 1 :(得分:0)
如果只想保存管理路由,只需读取已登录的用户,如果已登录的用户是admin,则isAdmin为true,然后根据此返回true或false。
admin-auth.service.ts
canActivate() {
return this.auth.user$.pipe(map(user => {
if (user.isAdmin) {
return true;
}
return false;
}));
答案 2 :(得分:0)
Activate必须返回什么? 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)
);
}