-
-
Save bdefore/8ae7e8e4a89700ba34e9 to your computer and use it in GitHub Desktop.
Redux auth duck
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var {handleResponse} = require('.utils') | |
var {setErrorMessages} = require('./messages') | |
var CHECK_TOKEN = 'auth/CHECK_TOKEN' | |
var CHECK_TOKEN_FAILURE = 'auth/CHECK_TOKEN_FAILURE' | |
var CHECK_TOKEN_SUCCESS = 'auth/CHECK_TOKEN_SUCCESS' | |
var LOGIN = 'auth/LOGIN' | |
var LOGIN_FAILURE = 'auth/LOGIN_FAILURE' | |
var LOGIN_SUCCESS = 'auth/LOGIN_SUCCESS' | |
var SHOWED_WELCOME = 'auth/SHOWED_WELCOME' | |
var LOGOUT = 'auth/LOGOUT' | |
var json = window.localStorage.auth | |
var initialState = json ? JSON.parse(json) : {token: null, user: null} | |
function auth(state={ // eslint-disable-line space-infix-ops | |
...initialState, | |
checkingToken: false, | |
loggingIn: false, | |
showWelcome: false | |
}, action) { | |
switch (action.type) { | |
case CHECK_TOKEN: | |
return {...state, checkingToken: true} | |
case CHECK_TOKEN_FAILURE: | |
case CHECK_TOKEN_SUCCESS: | |
return {...state, checkingToken: false} | |
case LOGIN: | |
return {...state, loggingIn: true} | |
case LOGIN_FAILURE: | |
return {...state, loggingIn: false} | |
case LOGIN_SUCCESS: | |
window.localStorage.auth = JSON.stringify(action.payload) | |
return {...state, loggingIn: false, showWelcome: true, ...action.payload} | |
case SHOWED_WELCOME: | |
return {...state, showWelcome: false} | |
case LOGOUT: | |
delete window.localStorage.auth | |
return {...state, token: null, user: null} | |
} | |
return state | |
} | |
auth.checkToken = () => (dispatch, getState) => { | |
dispatch({type: CHECK_TOKEN}) | |
window.fetch('/api/check-token', { | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
method: 'POST', | |
body: JSON.stringify({token: getState().auth.token}) | |
}) | |
.then(handleResponse) | |
.then(({valid}) => { | |
if (!valid) { | |
dispatch(auth.logout()) | |
dispatch(setErrorMessages(['Login expired - please log in again.'])) | |
} | |
dispatch({type: CHECK_TOKEN_SUCCESS}) | |
}) | |
.catch(error => { | |
dispatch(setErrorMessages([`Error checking authentication token: ${error.message}`])) | |
dispatch({type: CHECK_TOKEN_FAILURE}) | |
}) | |
} | |
auth.login = (username, password) => dispatch => { | |
dispatch({type: LOGIN}) | |
window.fetch('/api/authenticate', { | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
method: 'POST', | |
body: JSON.stringify({username, password}) | |
}) | |
.then(handleResponse) | |
.then(payload => dispatch({type: LOGIN_SUCCESS, payload})) | |
.catch(error => { | |
dispatch(setErrorMessages([`Error logging in: ${error.message}`])) | |
dispatch({type: LOGIN_FAILURE}) | |
}) | |
} | |
auth.logout = () => ({type: LOGOUT}) | |
auth.showedWelcome = () => ({type: SHOWED_WELCOME}) | |
auth.LOGOUT = LOGOUT | |
module.exports = auth |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var SET_ERROR_MESSAGES = 'messages/SET_ERROR_MESSAGES' | |
var FLASH_SUCCESS_MESSAGE = 'messages/FLASH_SUCCESS_MESSAGE' | |
var CLEAR_ERROR_MESSAGES = 'messages/CLEAR_ERROR_MESSAGES' | |
var CLEAR_SUCCESS_MESSAGE = 'messages/CLEAR_SUCCESS_MESSAGE' | |
var CLEAR_MESSAGES = 'messages/CLEAR_MESSAGES' | |
function messages(state={ // eslint-disable-line space-infix-ops | |
errorMessages: null, | |
successMessage: null, | |
successTimeout: null | |
}, action) { | |
switch (action.type) { | |
case SET_ERROR_MESSAGES: | |
return {...state, errorMessages: action.messages} | |
case FLASH_SUCCESS_MESSAGE: | |
return {...state, successMessage: action.message, successTimeout: action.timeout} | |
case CLEAR_ERROR_MESSAGES: | |
return {...state, errorMessages: null} | |
case CLEAR_MESSAGES: | |
return {...state, errorMessages: null, successMessage: null, successTimeout: null} | |
case CLEAR_SUCCESS_MESSAGE: | |
return {...state, successMessage: null, successTimeout: null} | |
} | |
return state | |
} | |
function maybeClearTimeout(timeout) { | |
if (timeout) { | |
window.clearTimeout(timeout) | |
} | |
} | |
messages.flashSuccessMessage = (message, dismissAfter=3000) => (dispatch, getState) => { // eslint-disable-line space-infix-ops | |
maybeClearTimeout(getState().messages.successTimeout) | |
var timeout = window.setTimeout(() => dispatch({type: CLEAR_SUCCESS_MESSAGE}), dismissAfter) | |
dispatch({type: FLASH_SUCCESS_MESSAGE, message, timeout}) | |
} | |
messages.setErrorMessages = (messages) => ({type: SET_ERROR_MESSAGES, messages}) | |
messages.clearErrorMessages = () => ({type: CLEAR_ERROR_MESSAGES}) | |
messages.clearMessages = () => (dispatch, getState) => { | |
maybeClearTimeout(getState().messages.successTimeout) | |
dispatch({type: CLEAR_MESSAGES}) | |
} | |
messages.clearSuccessMessage = () => (dispatch, getState) => { | |
maybeClearTimeout(getState().messages.successTimeout) | |
dispatch({type: CLEAR_SUCCESS_MESSAGE}) | |
} | |
module.exports = messages |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var JSON_CONTENT_TYPE_CHECK = /application\/json/ | |
/** | |
* Throws an error if a window.fetch response has a non-2XX status code, using a | |
* 'message' property from response JSON if present, otherwise using the | |
* response status and text. | |
* For successful responses, returns a JSON promise or the response itself based | |
* on the content-type header. | |
*/ | |
function handleResponse(response) { | |
var isJSON = JSON_CONTENT_TYPE_CHECK.test(response.headers.get('content-type')) | |
if (response.ok) { | |
return isJSON ? response.json() : response | |
} | |
if (isJSON) { | |
return response.json().then(json => { | |
var error = new Error(`${response.statusText}: ${json.message}`) | |
error.response = response | |
throw error | |
}) | |
} | |
else { | |
return response.text().then(text => { | |
var error = new Error(`${response.statusText}${text && `: ${text}`}`) | |
error.response = response | |
throw error | |
}) | |
} | |
} | |
module.exports = {handleResponse} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment