diff --git a/client/index.js b/client/index.js index e5e7028aed..bb31086834 100644 --- a/client/index.js +++ b/client/index.js @@ -18,8 +18,10 @@ import render from '../common/app/utils/render'; const log = debug('fcc:client'); const DOMContainer = document.getElementById('fcc'); const initialState = window.__fcc__.data; +const csrfToken = window.__fcc__.csrf.token; +initialState.app.csrfToken = csrfToken; -const serviceOptions = { xhrPath: '/services' }; +const serviceOptions = { xhrPath: '/services', context: { _csrf: csrfToken } }; Rx.config.longStackSupport = !!debug.enabled; const history = createHistory(); diff --git a/common/app/redux/reducer.js b/common/app/redux/reducer.js index 34520a7514..ef189c9390 100644 --- a/common/app/redux/reducer.js +++ b/common/app/redux/reducer.js @@ -30,6 +30,7 @@ export default handleActions( username: null, picture: null, points: 0, - isSignedIn: false + isSignedIn: false, + csrfToken: '' } ); diff --git a/common/app/routes/Hikes/redux/answer-saga.js b/common/app/routes/Hikes/redux/answer-saga.js index 1442778d1b..8189f74009 100644 --- a/common/app/routes/Hikes/redux/answer-saga.js +++ b/common/app/routes/Hikes/redux/answer-saga.js @@ -21,7 +21,7 @@ function handleAnswer(getState, dispatch, next, action) { const state = getState(); const { id, name, challengeType, tests } = getCurrentHike(state); const { - app: { isSignedIn }, + app: { isSignedIn, csrfToken }, hikesApp: { currentQuestion, delta = [ 0, 0 ] @@ -76,7 +76,7 @@ function handleAnswer(getState, dispatch, next, action) { let updateUser$; if (isSignedIn) { - const body = { id, name, challengeType: +challengeType }; + const body = { id, name, challengeType: +challengeType, _csrf: csrfToken }; updateUser$ = postJSON$('/completed-challenge', body) // if post fails, will retry once .retry(3) diff --git a/common/app/routes/Hikes/redux/reducer.js b/common/app/routes/Hikes/redux/reducer.js index bb0b130089..c48094ce75 100644 --- a/common/app/routes/Hikes/redux/reducer.js +++ b/common/app/routes/Hikes/redux/reducer.js @@ -80,11 +80,15 @@ export default handleActions( [types.goToNextHike]: state => ({ ...state, currentHike: findNextHikeName(state.hikes, state.currentHike), - shouldShowQuestions: false, - currentQuestion: 1, mouse: [ 0, 0 ] }), + [types.transitionHike]: state => ({ + ...state, + showQuestions: false, + currentQuestion: 1 + }), + [types.fetchHikesCompleted]: (state, { payload }) => { const { hikes, currentHike } = payload; diff --git a/server/middlewares/global-locals.js b/server/middlewares/global-locals.js index fbd0680731..1871eb95ff 100644 --- a/server/middlewares/global-locals.js +++ b/server/middlewares/global-locals.js @@ -3,6 +3,9 @@ export default function globalLocals() { // Make user object available in templates. res.locals.user = req.user; res.locals._csrf = req.csrfToken ? req.csrfToken() : null; + if (req.csrfToken) { + res.expose({ token: res.locals._csrf }, 'csrf'); + } next(); }; }