Angular Firebase+;ngrx+;身份验证的多个提供程序

Angular Firebase+;ngrx+;身份验证的多个提供程序,angular,firebase,firebase-authentication,ngrx,Angular,Firebase,Firebase Authentication,Ngrx,Firebase有一个奇怪的场景,当有人首先向google提供商登录时,您将无法向您在本问题中看到的其他提供商登录 最后,我按照上述问题的2个第一个答案实现了这一点,但有1个问题和1个改进 问题是,为什么当我使用异步内部catchError时,它期望正常的操作而不是可观察的操作 改进之处在于,当我调用弹出窗口时,有没有办法隐藏它?或者避免再次调用SigninProvider操作?(原因是用户将看到2个弹出窗口) 全面效果 @Effect() signInProvider: Observa

Firebase有一个奇怪的场景,当有人首先向google提供商登录时,您将无法向您在本问题中看到的其他提供商登录

最后,我按照上述问题的2个第一个答案实现了这一点,但有1个问题和1个改进

问题是,为什么当我使用异步内部catchError时,它期望正常的操作而不是可观察的操作

改进之处在于,当我调用弹出窗口时,有没有办法隐藏它?或者避免再次调用SigninProvider操作?(原因是用户将看到2个弹出窗口)

全面效果

@Effect()
    signInProvider: Observable<Action> = this.actions$.pipe(
        ofType(AuthActionTypes.SIGNIN_PROVIDER),
        map((action: SigninProvider) => action.payload),
        switchMap((provider) => {
            let result: any;
            let provi = provider;
            if (provider === 'google') {
                result = this.firebaseAuthService.signInGoogleLogin();
            } else if (provider === 'facebook') {
                result = this.firebaseAuthService.signInFacebookLogin();
            } else if (provider === 'twitter') {
                result = this.firebaseAuthService.signInTwitterLogin();
            }

            const resultAction: Observable<Action> = result.pipe(
                switchMap((userSignIn) => {
                    console.log("TCL: AuthEffects -> userSignIn", userSignIn)
                    return combineLatest(this.afAuth.authState.pipe(take(1)), of(userSignIn));
                }),
                switchMap(([user, userFromProvider]) => {
                    console.log("TCL: AuthEffects -> user", user)
                    const userEmail = user.email ? user.email : userFromProvider.additionalUserInfo.profile.email;
                    const userDto: CreateUserProviderDto = {
                        uid: user.uid,
                        fullName: user.displayName,
                        username: userEmail,
                        email: userEmail,
                        terms: true
                    };
                    return combineLatest(of(user), from(user.getIdToken()), this.usersService.usersSignInProviderPost(userDto));
                }),
                map(([user, token, userFromBackend]) => {
                    const currentUser: CurrentUser = {
                        token: token, refreshToken: user.refreshToken, user: {
                            _id: userFromBackend._id,
                            uid: userFromBackend.uid,
                            email: userFromBackend.email,
                            profile: userFromBackend.profile,
                            fullName: userFromBackend.fullName,
                            username: userFromBackend.username
                        }
                    };
                    this.localStorageService
                        .setItem(AUTH_KEY, {
                            token: token,
                            refreshToken: user.refreshToken,
                            isAuthenticated: true,
                            user: currentUser.user
                        });
                    this.ngZone.run(() => {
                        this.router.navigate(['/']);
                    });
                    return new SigninProviderSuccess(currentUser);
                }),
                catchError(async (error) => {
                    let displayMessage;
                    if (error.email && error.credential && error.code === 'auth/account-exists-with-different-credential') {
                        const providers = await this.afAuth.auth.fetchSignInMethodsForEmail(error.email)
                        const firstPopupProviderMethod =
                            providers.find(p => this.firebaseAuthService.supportedPopupSignInMethods.includes(p));

                        // Test: Could this happen with email link then trying social provider?
                        if (!firstPopupProviderMethod) {
                            throw new Error(`Your account is linked to a provider that isn't supported.`);
                        }

                        const linkedProvider = this.firebaseAuthService.getProvider(firstPopupProviderMethod);
                        linkedProvider.setCustomParameters({ login_hint: error.email });

                        const resultProvider = await this.afAuth.auth.signInWithPopup(linkedProvider);
                        await resultProvider.user.linkWithCredential(error.credential);

                        return new SigninProvider(provi);
                    } else if (typeof error === 'object'
                        && error !== null
                        && error.hasOwnProperty('code')
                        && error.hasOwnProperty('message')) {
                        const errorNoTypes: any = { ...error };
                        displayMessage = `${errorNoTypes.code} - ${error.message}`;
                        this.toastrService.danger('Try it again!', displayMessage, {
                            duration: 8000
                        });
                    }
                    return new RetrieveError(error);
                }),

            );
            return resultAction;
        })

    );
@Effect()
signInProvider:Observable=此.actions$.pipe(
ofType(AuthActionTypes.SIGNIN_PROVIDER),
映射((操作:SigninProvider)=>操作有效负载),
开关映射((提供程序)=>{
让结果:任何;
设provi=provider;
如果(提供程序=='google'){
结果=this.firebaseAuthService.SigningLogleLogin();
}else if(提供程序=='facebook'){
结果=this.firebaseAuthService.signInFacebookLogin();
}else if(提供程序==='twitter'){
结果=this.firebaseAuthService.signInTwitterLogin();
}
const resultAction:Observable=result.pipe(
开关映射((用户登录)=>{
log(“TCL:AuthEffects->userSignIn”,userSignIn)
返回combineLatest(this.afAuth.authState.pipe(take(1)),of(userSignIn));
}),
switchMap(([user,userFromProvider])=>{
log(“TCL:authfacts->user”,user)
const userEmail=user.email?user.email:userFromProvider.additionalUserInfo.profile.email;
const userDto:CreateUserProviderDto={
uid:user.uid,
全名:user.displayName,
用户名:userEmail,
电子邮件:userEmail,
术语:正确
};
返回combineTest(of(user),from(user.getIdToken()),this.usersService.usersSignInProviderPost(userDto));
}),
映射([user,token,userFromBackend])=>{
常数currentUser:currentUser={
令牌:令牌,刷新令牌:用户。刷新令牌,用户:{
_id:userFromBackend.\u id,
uid:userFromBackend.uid,
电子邮件:userFromBackend.email,
配置文件:userFromBackend.profile,
全名:userFromBackend.fullName,
用户名:userFromBackend.username
}
};
这是localStorageService
.setItem(身份验证密钥{
令牌:令牌,
refreshToken:user.refreshToken,
我证实:是的,
用户:currentUser.user
});
此.ngZone.run(()=>{
this.router.navigate(['/']);
});
返回新的SigninProviderSuccess(当前用户);
}),
catchError(异步(错误)=>{
让我们显示消息;
if(error.email&&error.credential&&error.code===='auth/account以不同的凭据存在'){
const providers=wait this.afAuth.auth.fetchSigningMethodForemail(error.email)
常数firstPopupProviderMethod=
providers.find(p=>this.firebaseAuthService.supportedPopupSigningMethods.includes(p));
//测试:这会发生在电子邮件链接,然后尝试社交提供商?
如果(!firstPopupProviderMethod){
抛出新错误(`您的帐户链接到不受支持的提供商。`);
}
const linkedProvider=this.firebaseAuthService.getProvider(firstPopupProviderMethod);
setCustomParameters({login\u hint:error.email});
const resultProvider=wait this.afAuth.auth.signInWithPopup(linkedProvider);
等待resultProvider.user.linkWithCredential(错误.credential);
返回新的签名提供者(provi);
}else if(错误类型==='object'
&&错误!==null
&&错误。hasOwnProperty('code'))
&&错误。hasOwnProperty('message')){
const errorNoTypes:any={…error};
displayMessage=`${errorNoTypes.code}-${error.message}`;
this.toastrService.danger('再试一次!'),displayMessage{
持续时间:8000
});
}
返回新的RetrieveError(错误);
}),
);
返回结果;
})
);
@Effect()
    signInProvider: Observable<Action> = this.actions$.pipe(
        ofType(AuthActionTypes.SIGNIN_PROVIDER),
        map((action: SigninProvider) => action.payload),
        switchMap((provider) => {
            let result: any;
            let provi = provider;
            if (provider === 'google') {
                result = this.firebaseAuthService.signInGoogleLogin();
            } else if (provider === 'facebook') {
                result = this.firebaseAuthService.signInFacebookLogin();
            } else if (provider === 'twitter') {
                result = this.firebaseAuthService.signInTwitterLogin();
            }

            const resultAction: Observable<Action> = result.pipe(
                switchMap((userSignIn) => {
                    console.log("TCL: AuthEffects -> userSignIn", userSignIn)
                    return combineLatest(this.afAuth.authState.pipe(take(1)), of(userSignIn));
                }),
                switchMap(([user, userFromProvider]) => {
                    console.log("TCL: AuthEffects -> user", user)
                    const userEmail = user.email ? user.email : userFromProvider.additionalUserInfo.profile.email;
                    const userDto: CreateUserProviderDto = {
                        uid: user.uid,
                        fullName: user.displayName,
                        username: userEmail,
                        email: userEmail,
                        terms: true
                    };
                    return combineLatest(of(user), from(user.getIdToken()), this.usersService.usersSignInProviderPost(userDto));
                }),
                map(([user, token, userFromBackend]) => {
                    const currentUser: CurrentUser = {
                        token: token, refreshToken: user.refreshToken, user: {
                            _id: userFromBackend._id,
                            uid: userFromBackend.uid,
                            email: userFromBackend.email,
                            profile: userFromBackend.profile,
                            fullName: userFromBackend.fullName,
                            username: userFromBackend.username
                        }
                    };
                    this.localStorageService
                        .setItem(AUTH_KEY, {
                            token: token,
                            refreshToken: user.refreshToken,
                            isAuthenticated: true,
                            user: currentUser.user
                        });
                    this.ngZone.run(() => {
                        this.router.navigate(['/']);
                    });
                    return new SigninProviderSuccess(currentUser);
                }),
                catchError(async (error) => {
                    let displayMessage;
                    if (error.email && error.credential && error.code === 'auth/account-exists-with-different-credential') {
                        const providers = await this.afAuth.auth.fetchSignInMethodsForEmail(error.email)
                        const firstPopupProviderMethod =
                            providers.find(p => this.firebaseAuthService.supportedPopupSignInMethods.includes(p));

                        // Test: Could this happen with email link then trying social provider?
                        if (!firstPopupProviderMethod) {
                            throw new Error(`Your account is linked to a provider that isn't supported.`);
                        }

                        const linkedProvider = this.firebaseAuthService.getProvider(firstPopupProviderMethod);
                        linkedProvider.setCustomParameters({ login_hint: error.email });

                        const resultProvider = await this.afAuth.auth.signInWithPopup(linkedProvider);
                        await resultProvider.user.linkWithCredential(error.credential);

                        return new SigninProvider(provi);
                    } else if (typeof error === 'object'
                        && error !== null
                        && error.hasOwnProperty('code')
                        && error.hasOwnProperty('message')) {
                        const errorNoTypes: any = { ...error };
                        displayMessage = `${errorNoTypes.code} - ${error.message}`;
                        this.toastrService.danger('Try it again!', displayMessage, {
                            duration: 8000
                        });
                    }
                    return new RetrieveError(error);
                }),

            );
            return resultAction;
        })

    );