import { Injectable } from '@angular/core' ; import { Actions , Effect , ofType } from '@ngrx/effects' ; import { AuthService } from '../services/auth.service' ; import { Router } from '@angular/router' ; import { Observable , of , defer } from 'rxjs' ; import { map , switchMap , catchError , tap , take } from 'rxjs/operators' ; import * as auth from './../store/auth.actions' ; import { User } from '../models/user.model' ; import { GravatarService } from '../../shared/services/gravatar.service' ; @ Injectable ( ) export class AuthEffects { constructor ( private actions$ , private authService , private gravatarService , private router ) { } @ Effect ( ) registerAction$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . REGISTER_REQUESTED ) , map ( ( action ) => action . payload ) , switchMap ( payload => this . authService . register ( payload . email , payload . password ) . pipe ( map ( ( res ) => { const gravatarUrl = this . gravatarService . getUserGravatar ( res . user . email ) ; const user = { uid : res . user . uid , displayName : payload . username || res . user . displayName , email : res . user . email , providerId : res . additionalUserInfo . providerId , photoUrl : res . user . photoURL || gravatarUrl , isNewUser : res . additionalUserInfo . isNewUser , isAdmin : false , isOnline : true } ; return user ; } ) , switchMap ( ( user ) => { return [ new auth . RegisterCompleted ( ) , new auth . LoginSuccess ( { user } ) , new auth . UpdateProfile ( { displayName : payload . username , photoUrl : user . photoUrl } ) , new auth . SaveUser ( { user } ) ] ; } ) , tap ( ( ) => { this . router . navigateByUrl ( '' ) ; } ) , catchError ( error => of ( new auth . AuthError ( { error } ) ) ) ) ) ) ; @ Effect ( { dispatch : false } ) saveUser$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . SAVE_USER ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => this . authService . saveUser ( payload . user ) ) ) ; @ Effect ( { dispatch : false } ) updateOnlineStatus$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . UPDATE_ONLINE_STATUS ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => this . authService . updateOnlineStatus ( payload . uid , payload . status ) ) ) ; @ Effect ( ) checkUserRole$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . CHECK_USER_ROLE ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => this . authService . checkUserRole ( payload . uid ) . pipe ( map ( ( isAdmin ) => { return new auth . UpdateUserRole ( { isAdmin } ) ; } ) , catchError ( ( error ) => of ( new auth . AuthError ( { error } ) ) ) ) ) ) ; @ Effect ( ) updateProfile$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . UPDATE_PROFILE ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => this . authService . updateProfile ( payload . displayName , payload . photoUrl ) . pipe ( map ( ( ) => { const currentUser = this . authService . getCurrentUser ( ) ; const updatedUser = { uid : currentUser . uid || null , displayName : currentUser . displayName || null , email : currentUser . email || null , providerId : currentUser . providerData [ 0 ] . providerId || null , photoUrl : currentUser . photoURL || null } ; return new auth . UpdateProfileSuccess ( { user : updatedUser } ) ; } ) , catchError ( ( error ) => of ( new auth . AuthError ( error ) ) ) ) ) ) ; @ Effect ( ) loginAction$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . LOGIN_REQUESTED ) , map ( ( action ) => action . payload ) , switchMap ( payload => this . authService . login ( payload . email , payload . password ) . pipe ( map ( ( res ) => { const user = { uid : res . user . uid , displayName : res . user . displayName , email : res . user . email , providerId : res . additionalUserInfo . providerId , photoUrl : res . user . photoURL , isNewUser : res . additionalUserInfo . isNewUser } ; return new auth . LoginSuccess ( { user } ) ; } ) , tap ( ( ) => this . router . navigateByUrl ( '' ) ) , catchError ( error => of ( new auth . AuthError ( { error } ) ) ) ) ) ) ; @ Effect ( ) loginSuccess$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . LOGIN_SUCCESS ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => { return [ new auth . UpdateOnlineStatus ( { uid : payload . user . uid , status : true } ) , new auth . CheckUserRole ( { uid : payload . user . uid } ) ] ; } ) ) ; @ Effect ( ) socialLogin$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . SOCIAL_LOGIN ) , map ( ( action ) => action . payload ) , switchMap ( payload => this . authService . socialLogin ( payload . authProvider ) . pipe ( map ( ( res ) => { const user = { uid : res . user . uid , displayName : res . user . displayName , email : res . user . email , providerId : res . additionalUserInfo . providerId , photoUrl : res . user . photoURL , isNewUser : res . additionalUserInfo . isNewUser } ; return user ; } ) , switchMap ( ( user ) => { if ( user . isNewUser ) { return [ new auth . LoginSuccess ( { user } ) , new auth . SaveUser ( { user } ) , new auth . CheckUserRole ( { uid : user . uid } ) ] ; } else { return [ new auth . LoginSuccess ( { user } ) , new auth . CheckUserRole ( { uid : user . uid } ) ] ; } } ) , tap ( ( ) => this . router . navigateByUrl ( '' ) ) , catchError ( error => { return of ( new auth . AuthError ( { error } ) ) ; } ) ) ) ) ; @ Effect ( ) logoutAction$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . LOGOUT_REQUESTED ) , map ( ( action ) => action . payload ) , switchMap ( ( payload ) => this . authService . logout ( payload . user . uid ) . pipe ( map ( ( ) => ( new auth . LogoutCompleted ( ) ) ) , tap ( ( ) => this . router . navigateByUrl ( '' ) ) , catchError ( error => { return of ( new auth . AuthError ( { error } ) ) ; } ) ) ) ) ; @ Effect ( ) getUser$ = this . actions$ . pipe ( ofType ( auth . AuthActionTypes . GET_USER ) , switchMap ( ( ) => this . authService . getAuthState ( ) . pipe ( take ( 1 ) , map ( ( authData ) => { if ( authData ) { const user = { uid : authData . uid , displayName : authData . displayName , email : authData . email , providerId : authData . providerData [ 0 ] . providerId , photoUrl : authData . photoURL , } ; return new auth . LoginSuccess ( { user } ) ; } else { return new auth . LoginFailed ( ) ; } } ) , catchError ( error => of ( new auth . AuthError ( { error } ) ) ) ) ) ) ; @ Effect ( ) init$ : Observable < any > = defer ( ( ) => { return of ( new auth . GetUser ( ) ) ; } ) ; }