import axios from 'axios' ; import { Dispatch , Store , } from 'redux' ; import { AuthResponse , DeviceStorage , VerificationParams , UserAttributes , UserRegistrationDetails , UserSignInCredentials , UserSignOutCredentials , ActionsExport , REGISTRATION_REQUEST_SENT , REGISTRATION_REQUEST_SUCCEEDED , REGISTRATION_REQUEST_FAILED , VERIFY_TOKEN_REQUEST_SENT , VERIFY_TOKEN_REQUEST_SUCCEEDED , VERIFY_TOKEN_REQUEST_FAILED , SIGNIN_REQUEST_SENT , SIGNIN_REQUEST_SUCCEEDED , SIGNIN_REQUEST_FAILED , SIGNOUT_REQUEST_SENT , SIGNOUT_REQUEST_SUCCEEDED , SIGNOUT_REQUEST_FAILED , SET_HAS_VERIFICATION_BEEN_ATTEMPTED , RegistrationRequestSentAction , RegistrationRequestSucceededAction , RegistrationRequestFailedAction , VerifyTokenRequestSentAction , VerifyTokenRequestSucceededAction , VerifyTokenRequestFailedAction , SignInRequestSentAction , SignInRequestSucceededAction , SignInRequestFailedAction , SignOutRequestSentAction , SignOutRequestSucceededAction , SignOutRequestFailedAction , SetHasVerificationBeenAttemptedAction , } from './types' ; import AsyncLocalStorage from './AsyncLocalStorage' ; import { deleteAuthHeaders , deleteAuthHeadersFromDeviceStorage , getUserAttributesFromResponse , persistAuthHeadersInDeviceStorage , setAuthHeaders , } from './services/auth' ; export const registrationRequestSent = ( ) : RegistrationRequestSentAction => ( { type : REGISTRATION_REQUEST_SENT , } ) ; export const registrationRequestSucceeded = ( userAttributes ) : RegistrationRequestSucceededAction => ( { type : REGISTRATION_REQUEST_SUCCEEDED , payload : { userAttributes , } , } ) ; export const registrationRequestFailed = ( ) : RegistrationRequestFailedAction => ( { type : REGISTRATION_REQUEST_FAILED , } ) ; export const verifyTokenRequestSent = ( ) : VerifyTokenRequestSentAction => ( { type : VERIFY_TOKEN_REQUEST_SENT , } ) ; export const verifyTokenRequestSucceeded = ( userAttributes ) : VerifyTokenRequestSucceededAction => ( { type : VERIFY_TOKEN_REQUEST_SUCCEEDED , payload : { userAttributes , } , } ) ; export const verifyTokenRequestFailed = ( ) : VerifyTokenRequestFailedAction => ( { type : VERIFY_TOKEN_REQUEST_FAILED , } ) ; export const signInRequestSent = ( ) : SignInRequestSentAction => ( { type : SIGNIN_REQUEST_SENT , } ) ; export const signInRequestSucceeded = ( userAttributes ) : SignInRequestSucceededAction => ( { type : SIGNIN_REQUEST_SUCCEEDED , payload : { userAttributes , } , } ) ; export const signInRequestFailed = ( ) : SignInRequestFailedAction => ( { type : SIGNIN_REQUEST_FAILED , } ) ; export const signOutRequestSent = ( ) : SignOutRequestSentAction => ( { type : SIGNOUT_REQUEST_SENT , } ) ; export const signOutRequestSucceeded = ( ) : SignOutRequestSucceededAction => ( { type : SIGNOUT_REQUEST_SUCCEEDED , } ) ; export const signOutRequestFailed = ( ) : SignOutRequestFailedAction => ( { type : SIGNOUT_REQUEST_FAILED , } ) ; export const setHasVerificationBeenAttempted = ( hasVerificationBeenAttempted ) : SetHasVerificationBeenAttemptedAction => ( { type : SET_HAS_VERIFICATION_BEEN_ATTEMPTED , payload : { hasVerificationBeenAttempted , } , } ) ; const generateAuthActions = ( config ) : ActionsExport => { const { authUrl , storage , userAttributes , userRegistrationAttributes , } = config ; const Storage = Boolean ( storage . flushGetRequests ) ? storage : AsyncLocalStorage ; const registerUser = ( userRegistrationDetails ) => async function ( dispatch ) : Promise < void > { dispatch ( registrationRequestSent ( ) ) ; const { email , password , passwordConfirmation , } = userRegistrationDetails ; const data = { email , password , password_confirmation : passwordConfirmation , } ; Object . keys ( userRegistrationAttributes ) . forEach ( ( key ) => { const backendKey = userRegistrationAttributes [ key ] ; data [ backendKey ] = userRegistrationDetails [ key ] ; } ) ; try { const response = await axios ( { method : 'POST' , url : authUrl , data , } ) ; setAuthHeaders ( response . headers ) ; persistAuthHeadersInDeviceStorage ( Storage , response . headers ) ; const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response ) ; dispatch ( registrationRequestSucceeded ( userAttributesToSave ) ) ; } catch ( error ) { dispatch ( registrationRequestFailed ( ) ) ; throw error ; } } ; const verifyToken = ( verificationParams ) => async function ( dispatch ) : Promise < void > { dispatch ( verifyTokenRequestSent ( ) ) ; try { const response = await axios ( { method : 'GET' , url : `${ authUrl }/validate_token` , params : verificationParams , } ) ; setAuthHeaders ( response . headers ) ; persistAuthHeadersInDeviceStorage ( Storage , response . headers ) ; const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response ) ; dispatch ( verifyTokenRequestSucceeded ( userAttributesToSave ) ) ; } catch ( error ) { dispatch ( verifyTokenRequestFailed ( ) ) ; } } ; const signInUser = ( userSignInCredentials ) => async function ( dispatch ) : Promise < void > { dispatch ( signInRequestSent ( ) ) ; const { email , password , } = userSignInCredentials ; try { const response = await axios ( { method : 'POST' , url : `${ authUrl }/sign_in` , data : { email , password , } , } ) ; setAuthHeaders ( response . headers ) ; persistAuthHeadersInDeviceStorage ( Storage , response . headers ) ; const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response ) ; dispatch ( signInRequestSucceeded ( userAttributesToSave ) ) ; } catch ( error ) { dispatch ( signInRequestFailed ( ) ) ; throw error ; } } ; const signOutUser = ( ) => async function ( dispatch ) : Promise < void > { const userSignOutCredentials = { 'access-token' : await Storage . getItem ( 'access-token' ) as string , client : await Storage . getItem ( 'client' ) as string , uid : await Storage . getItem ( 'uid' ) as string , } ; dispatch ( signOutRequestSent ( ) ) ; try { await axios ( { method : 'DELETE' , url : `${ authUrl }/sign_out` , data : userSignOutCredentials , } ) ; deleteAuthHeaders ( ) ; deleteAuthHeadersFromDeviceStorage ( Storage ) ; dispatch ( signOutRequestSucceeded ( ) ) ; } catch ( error ) { dispatch ( signOutRequestFailed ( ) ) ; throw error ; } } ; const verifyCredentials = async ( store ) : Promise < void > => { if ( await Storage . getItem ( 'access-token' ) ) { const verificationParams = { 'access-token' : await Storage . getItem ( 'access-token' ) as string , client : await Storage . getItem ( 'client' ) as string , uid : await Storage . getItem ( 'uid' ) as string , } ; store . dispatch < any > ( verifyToken ( verificationParams ) ) ; } else { store . dispatch ( setHasVerificationBeenAttempted ( true ) ) ; } } ; return { registerUser , verifyToken , signInUser , signOutUser , verifyCredentials , } ; } ; export default generateAuthActions ;