import fetch from 'isomorphic-unfetch'; import store from '../store'; import getUrl from '../../util/getUrl'; // define action types export const SET_USER = 'SET_USER'; export const LOGIN_PENDING = 'LOGIN_PENDING'; export const LOGIN_FAILED = 'LOGIN_FAILED'; export const LOGOUT = 'LOGOUT'; export const setUser = user => { store.dispatch({ type: SET_USER, data: user }); }; // setUser export const doLogout = () => { if(typeof window !== 'undefined') { window.localStorage.removeItem('jwt'); document.cookie = 'jwt=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;'; } store.dispatch({ type: LOGOUT }); }; // doLogout export async function doLogin (creds, jwt, noPend) { !noPend && store.dispatch({ type: LOGIN_PENDING }); const authReqOpts = { method: 'POST', credentials: 'include' }; const authReqHead = { headers: jwt ? { Authorization: jwt } : { 'Content-Type': 'application/json' } }; const authReqBody = jwt ? null : { body: JSON.stringify({...creds, strategy: 'local'}) }; const authReq = new Request(getUrl('auth'), { ...authReqOpts, ...authReqHead, ...authReqBody }); const authRes = await fetch(authReq).catch(err => { store.dispatch({ type: LOGIN_FAILED, data: err.message }); }); if(!authRes.ok) { let error; try { error = await authRes.json(); error = error.message; } catch (err) { error = authRes.status === 429 ? 'Max login attempts reached' : 'An error occurred during login'; } return store.dispatch({ type: LOGIN_FAILED, data: error }); } const { accessToken } = await authRes.json(); const payload = accessToken.split('.')[1]; const { userId } = JSON.parse(atob(payload)); const userReq = new Request(getUrl(`/users/${userId}`), { headers: { Authorization: accessToken } }); const userRes = await fetch(userReq); if(!userRes.ok) { return store.dispatch({ type: LOGIN_FAILED, data: 'failed to get user' }); } window.localStorage.setItem('jwt', accessToken); setUser(await userRes.json()); } // doLogin