2017-09-02 22:07:05 +00:00
import axios from 'axios'
2017-09-04 01:03:46 +00:00
import {
Dispatch ,
Store ,
} from 'redux'
2017-09-02 22:07:05 +00:00
import {
AuthResponse ,
VerificationParams ,
UserAttributes ,
UserRegistrationDetails ,
UserSignInCredentials ,
UserSignOutCredentials ,
2017-09-03 13:41:20 +00:00
ActionsExport ,
2017-09-02 22:07:05 +00:00
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 ,
RegistrationRequestSentAction ,
RegistrationRequestSucceededAction ,
RegistrationRequestFailedAction ,
VerifyTokenRequestSentAction ,
VerifyTokenRequestSucceededAction ,
VerifyTokenRequestFailedAction ,
SignInRequestSentAction ,
SignInRequestSucceededAction ,
SignInRequestFailedAction ,
SignOutRequestSentAction ,
SignOutRequestSucceededAction ,
SignOutRequestFailedAction ,
} from './types'
import {
deleteAuthHeaders ,
deleteAuthHeadersFromLocalStorage ,
2017-09-15 18:21:02 +00:00
getUserAttributesFromResponse ,
persistAuthHeadersInLocalStorage ,
setAuthHeaders ,
2017-09-02 22:07:05 +00:00
} from './services/auth' // <- maybe this is where you pass in the platform paramter, specifying if it is for a browser or for React Native
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pure Redux actions:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
export const registrationRequestSent = ( ) : RegistrationRequestSentAction = > ( {
type : REGISTRATION_REQUEST_SENT ,
} )
export const registrationRequestSucceeded = ( userAttributes : 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 : 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 : 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 ,
} )
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Async Redux Thunk actions:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2017-09-04 00:20:23 +00:00
// what is the second argument here? it needs to contain configs for (1) userRegistrationDetails, (2) userAttributes, (3) maybe even the authUrl... just make it a simple one-argument function
// we'll also want the userAttributes to pertain to the end-user's initial state and heaven forbid reducers
// actually, userSignInCredentials, userSignOutCredentials, and verificationParams are always the same as per devise token auth
// const config = {
// authUrl: 'http://url.com',
// userAttributes: {
// firstName: 'name' // <- key is how the frontend knows it, value is how the backend knows it
// },
// userRegistrationAttributes: { <- this is for keys/vals IN ADDITION TO email, password and passwordConfirmation
// firstName: 'name'
// },
// }
const generateAuthActions = ( config : { [ key : string ] : any } ) : ActionsExport = > {
const {
authUrl ,
userAttributes ,
userRegistrationAttributes ,
} = config
2017-09-02 22:07:05 +00:00
const registerUser = (
userRegistrationDetails : UserRegistrationDetails ,
) = > async function ( dispatch : Dispatch < { } > ) : Promise < void > {
dispatch ( registrationRequestSent ( ) )
const {
email ,
password ,
passwordConfirmation ,
} = userRegistrationDetails
2017-09-04 00:20:23 +00:00
const data = {
email ,
password ,
password_confirmation : passwordConfirmation ,
}
Object . keys ( userRegistrationAttributes ) . forEach ( ( key : string ) = > {
const backendKey = userRegistrationAttributes [ key ]
data [ backendKey ] = userRegistrationDetails [ key ]
} )
2017-09-02 22:07:05 +00:00
try {
const response : AuthResponse = await axios ( {
method : 'POST' ,
url : authUrl ,
2017-09-04 00:20:23 +00:00
data ,
2017-09-02 22:07:05 +00:00
} )
setAuthHeaders ( response . headers )
2017-09-04 00:20:23 +00:00
// Have to check what type of platform it is, depending on the key provided by the end-user... like "browser", "iphone", or "android", etc.:
2017-09-02 22:07:05 +00:00
persistAuthHeadersInLocalStorage ( response . headers )
2017-09-04 01:03:46 +00:00
const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response )
2017-09-04 00:20:23 +00:00
dispatch ( registrationRequestSucceeded ( userAttributesToSave ) ) // <- need to make this reducer more flexible
2017-09-02 22:07:05 +00:00
} catch ( error ) {
dispatch ( registrationRequestFailed ( ) )
throw error
}
}
const verifyToken = (
verificationParams : VerificationParams ,
) = > async function ( dispatch : Dispatch < { } > ) : Promise < void > {
dispatch ( verifyTokenRequestSent ( ) )
try {
const response = await axios ( {
method : 'GET' ,
url : ` ${ authUrl } /validate_token ` ,
params : verificationParams ,
} )
setAuthHeaders ( response . headers )
2017-09-04 01:03:46 +00:00
// Have to check what type of platform it is, depending on the key provided by the end-user... like "browser", "iphone", or "android", etc.:
2017-09-02 22:07:05 +00:00
persistAuthHeadersInLocalStorage ( response . headers )
2017-09-04 01:03:46 +00:00
const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response )
dispatch ( verifyTokenRequestSucceeded ( userAttributesToSave ) )
2017-09-02 22:07:05 +00:00
} catch ( error ) {
dispatch ( verifyTokenRequestFailed ( ) )
}
}
const signInUser = (
userSignInCredentials : UserSignInCredentials ,
) = > async function ( dispatch : 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 )
2017-09-04 01:03:46 +00:00
// Have to check what type of platform it is, depending on the key provided by the end-user... like "browser", "iphone", or "android", etc.:
2017-09-02 22:07:05 +00:00
persistAuthHeadersInLocalStorage ( response . headers )
2017-09-04 01:03:46 +00:00
const userAttributesToSave = getUserAttributesFromResponse ( userAttributes , response )
dispatch ( signInRequestSucceeded ( userAttributesToSave ) )
2017-09-02 22:07:05 +00:00
} catch ( error ) {
dispatch ( signInRequestFailed ( ) )
throw error
}
}
2017-09-16 02:59:47 +00:00
const signOutUser = ( ) = > async function ( dispatch : Dispatch < { } > ) : Promise < void > {
const userSignOutCredentials : UserSignOutCredentials = {
'access-token' : localStorage . getItem ( 'access-token' ) as string ,
client : localStorage.getItem ( 'client' ) as string ,
uid : localStorage.getItem ( 'uid' ) as string ,
}
2017-09-02 22:07:05 +00:00
dispatch ( signOutRequestSent ( ) )
try {
await axios ( {
method : 'DELETE' ,
url : ` ${ authUrl } /sign_out ` ,
data : userSignOutCredentials ,
} )
deleteAuthHeaders ( )
2017-09-04 01:03:46 +00:00
// Have to check what type of platform it is, depending on the key provided by the end-user... like "browser", "iphone", or "android", etc.:
2017-09-02 22:07:05 +00:00
deleteAuthHeadersFromLocalStorage ( )
dispatch ( signOutRequestSucceeded ( ) )
} catch ( error ) {
dispatch ( signOutRequestFailed ( ) )
throw error
}
}
2017-09-04 01:03:46 +00:00
const verifyCredentials = ( store : Store < { } > ) : void = > {
// Gotta check what the platform is:
if ( localStorage . getItem ( 'access-token' ) ) {
const verificationParams : VerificationParams = {
'access-token' : localStorage . getItem ( 'access-token' ) as string ,
client : localStorage.getItem ( 'client' ) as string ,
uid : localStorage.getItem ( 'uid' ) as string ,
}
store . dispatch < any > ( verifyToken ( verificationParams ) )
}
}
2017-09-02 22:07:05 +00:00
return {
registerUser ,
verifyToken ,
signInUser ,
signOutUser ,
2017-09-04 01:03:46 +00:00
verifyCredentials ,
2017-09-02 22:07:05 +00:00
}
}
2017-09-03 13:50:52 +00:00
export default generateAuthActions