#angular #firebase #firebase-authentication #angularfire2
#angular #firebase #firebase-аутентификация #angularfire2
Вопрос:
У меня есть защита маршрута, которая пока работает, но я получаю это сообщение:
WARNING: the getAuth() API has changed behavior since adding support for Firebase 3.
This will return null for the initial value when the page loads, even if the user is actually logged in.
Please observe the actual authState asynchronously by subscribing to the auth service: af.auth.subscribe().
The getAuth method will be removed in future releases
Вот моя текущая защита:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire, FirebaseListObservable, AuthProviders, AuthMethods } from 'angularfire2';
import {Observable} from "rxjs/Rx";
@Injectable()
export class AuthFirebaseGuard implements CanActivate {
user={}
constructor(public af: AngularFire,
private router: Router
) {}
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot){
if (this.af.auth.getAuth().uid){
return true;
} else {
this.router.navigate(['login']);
return false;
}
}
}
Вот что я хочу изменить на:
@Injectable()
export class AuthFirebaseGuard implements CanActivate {
user={}
constructor(public af: AngularFire,
private router: Router
) {}
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot){
this.user = this.af.auth.subscribe(user => {
if (user) {
this.user = user.auth.providerData[0];
if (user.auth.emailVerified==false){
user.auth.sendEmailVerification().then(function() {
this.router.navigate(['login']);
return false;
});
} else {
return true;
}
}
else {
this.router.navigate(['login']);
return false;
}
});
}
}
Как мне дождаться завершения подписки?
Class 'AuthFirebaseGuard' incorrectly implements interface 'CanActivate'.
Types of property 'canActivate' are incompatible.
Type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => void' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable<boolean> | Pr...'.
Type 'void' is not assignable to type 'boolean | Observable<boolean> | Promise<boolean>'.
ERROR in [default] /Users/Documents/frontend/iboot/src/app/common/auth-firebase.gaurd.ts:14:13
Class 'AuthFirebaseGuard' incorrectly implements interface 'CanActivate'.
Types of property 'canActivate' are incompatible.
Type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => Observable<{}>' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable<boolean> | Pr...'.
Type 'Observable<{}>' is not assignable to type 'boolean | Observable<boolean> | Promise<boolean>'.
Type 'Observable<{}>' is not assignable to type 'Promise<boolean>'.
Property 'then' is missing in type 'Observable<{}>'.
ERROR in [default] /Users/Documents/frontend/iboot/src/app/common/auth-firebase.gaurd.ts:41:40
Argument of type 'firebase.Promise<any>' is not assignable to parameter of type 'Promise<any>'.
Types of property 'then' are incompatible.
Type '(onResolve?: (a: any) => any, onReject?: (a: Error) => any) => Promise<any>' is not assignable to type '{ <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected:...'.
Type 'firebase.Promise<any>' is not assignable to type 'Promise<any>'.
Ответ №1:
canActivate
может возвращать логическое значение, обещание или наблюдаемое, поэтому вы можете создать наблюдаемое, используя auth
наблюдаемое AngularFire2:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
return this.af.auth
// Observables returned by canActivate have to complete, so take the
// first emitted value from the auth observable.
.first()
// Use mergeMap to project the values emitted from the inner
// observables created using Observable.fromPromise and
// Observable.of. (If you weren't making the call to
// sendEmailVerification, you could just use the map operator
// and would return a boolean.)
.mergeMap((user) => {
if (user amp;amp; user.auth) {
if (!user.auth.emailVerified) {
return Observable.fromPromise(user.auth
.sendEmailVerification()
.then(() => {
this.router.navigate(['login']);
return false;
})
);
}
return Observable.of(true);
} else {
this.router.navigate(['login']);
return Observable.of(false);
}
});
}
Комментарии:
1. Я добавил сообщение об ошибке, которое я получаю при попытке вашего решения
2. Я убрал логику .sendEmailVerification(), и это сработало. В любом случае это не нужно. Спасибо!
3. Не беспокойтесь. Ошибка звучит как проблема с TypeScript с обещаниями, напечатанными на duck. Вы могли бы использовать его, чтобы успокоить TypeScript:
...sendEmailVerification().then(() => ... ) as Promise<any>