diff --git a/src/components/auth/actions.js b/src/components/auth/actions.js index 8f280fd..f0c3c70 100644 --- a/src/components/auth/actions.js +++ b/src/components/auth/actions.js @@ -2,6 +2,7 @@ import { routeActions } from 'react-router-redux'; import { updateUser, logout as logoutUser, changePassword as changeUserPassword, authenticate } from 'components/user/actions'; import request from 'services/request'; +import authentication from 'services/api/authentication'; export function login({login = '', password = '', rememberMe = false}) { const PASSWORD_REQUIRED = 'error.password_required'; @@ -9,28 +10,21 @@ export function login({login = '', password = '', rememberMe = false}) { const ACTIVATION_REQUIRED = 'error.account_not_activated'; return wrapInLoader((dispatch) => - request.post( - '/api/authentication/login', + authentication.login( {login, password, rememberMe} ) - .then((resp) => { - dispatch(updateUser({ - isGuest: false, - token: resp.jwt - })); - - return dispatch(authenticate(resp.jwt)); - }) + .then(authHandler(dispatch)) .catch((resp) => { - if (resp.errors.login === ACTIVATION_REQUIRED) { - return dispatch(needActivation()); - } else if (resp.errors.password === PASSWORD_REQUIRED) { - return dispatch(updateUser({ - username: login, - email: login - })); - } else if (resp.errors) { - if (resp.errors.login === LOGIN_REQUIRED && password) { + if (resp.errors) { + if (resp.errors.password === PASSWORD_REQUIRED) { + return dispatch(updateUser({ + username: login, + email: login + })); + } else if (resp.errors.login === ACTIVATION_REQUIRED) { + return dispatch(needActivation()); + } else if (resp.errors.login === LOGIN_REQUIRED && password) { + // return to the first step dispatch(logout()); } } @@ -76,14 +70,7 @@ export function recoverPassword({ '/api/authentication/recover-password', {key, newPassword, newRePassword} ) - .then((resp) => { - dispatch(updateUser({ - isGuest: false, - isActive: true - })); - - return dispatch(authenticate(resp.jwt)); - }) + .then(authHandler(dispatch)) .catch(validationErrorsHandler(dispatch, '/forgot-password')) ); } @@ -118,14 +105,7 @@ export function activate({key = ''}) { '/api/signup/confirm', {key} ) - .then((resp) => { - dispatch(updateUser({ - isGuest: false, - isActive: true - })); - - return dispatch(authenticate(resp.jwt)); - }) + .then(authHandler(dispatch)) .catch(validationErrorsHandler(dispatch, '/resend-activation')) ); } @@ -341,6 +321,10 @@ function needActivation() { }); } +function authHandler(dispatch) { + return (resp) => dispatch(authenticate(resp.access_token, resp.refresh_token)); +} + function validationErrorsHandler(dispatch, repeatUrl) { return (resp) => { if (resp.errors) { diff --git a/src/components/auth/password/PasswordBody.jsx b/src/components/auth/password/PasswordBody.jsx index ea9d80a..cd47753 100644 --- a/src/components/auth/password/PasswordBody.jsx +++ b/src/components/auth/password/PasswordBody.jsx @@ -32,6 +32,7 @@ export default class PasswordBody extends BaseAuthBody { {user.email || user.username} + diff --git a/src/components/user/User.js b/src/components/user/User.js index 8dc4a08..7e9672f 100644 --- a/src/components/user/User.js +++ b/src/components/user/User.js @@ -19,6 +19,7 @@ export default class User { id: null, uuid: null, token: '', + refreshToken: '', username: '', email: '', // will contain user's email or masked email diff --git a/src/components/user/actions.js b/src/components/user/actions.js index 13af82a..05f82ea 100644 --- a/src/components/user/actions.js +++ b/src/components/user/actions.js @@ -95,13 +95,21 @@ export function changePassword({ } -export function authenticate(token) { +export function authenticate(token, refreshToken) { if (!token || token.split('.').length !== 3) { throw new Error('Invalid token'); } return (dispatch) => { request.setAuthToken(token); - return dispatch(fetchUserData()); + + return dispatch(fetchUserData()).then((resp) => { + dispatch(updateUser({ + isGuest: false, + token, + refreshToken + })); + return resp; + }); }; } diff --git a/src/services/api/authentication.js b/src/services/api/authentication.js new file mode 100644 index 0000000..90282cd --- /dev/null +++ b/src/services/api/authentication.js @@ -0,0 +1,14 @@ +import request from 'services/request'; + +export default { + login({ + login = '', + password = '', + rememberMe = false + }) { + return request.post( + '/api/authentication/login', + {login, password, rememberMe} + ); + } +}; diff --git a/src/services/authFlow/PasswordState.js b/src/services/authFlow/PasswordState.js index 2bdd112..13e6c22 100644 --- a/src/services/authFlow/PasswordState.js +++ b/src/services/authFlow/PasswordState.js @@ -14,11 +14,12 @@ export default class PasswordState extends AbstractState { } } - resolve(context, {password}) { + resolve(context, {password, rememberMe}) { const {user} = context.getState(); context.run('login', { password, + rememberMe, login: user.email || user.username }) .then(() => context.setState(new CompleteState())); diff --git a/tests/services/authFlow/PasswordState.test.js b/tests/services/authFlow/PasswordState.test.js index 2606012..5a003de 100644 --- a/tests/services/authFlow/PasswordState.test.js +++ b/tests/services/authFlow/PasswordState.test.js @@ -48,6 +48,7 @@ describe('PasswordState', () => { (function() { const expectedLogin = 'login'; const expectedPassword = 'password'; + const expectedRememberMe = true; const testWith = (user) => { it(`should call login with email or username and password. User: ${JSON.stringify(user)}`, () => { @@ -58,11 +59,12 @@ describe('PasswordState', () => { 'login', sinon.match({ login: expectedLogin, - password: expectedPassword + password: expectedPassword, + rememberMe: expectedRememberMe, }) ).returns({then() {}}); - state.resolve(context, {password: expectedPassword}); + state.resolve(context, {password: expectedPassword, rememberMe: expectedRememberMe}); }); };