#48: fix the bug, whent account.current was requested without disabling refreshToken middleware

This commit is contained in:
SleepWalker 2016-11-08 08:30:53 +02:00
parent 0d8696b4f7
commit a2afac867a
7 changed files with 35 additions and 17 deletions

View File

@ -16,10 +16,12 @@ import { setLocale } from 'components/i18n/actions';
* @param {Account|object} account * @param {Account|object} account
* @param {string} account.token * @param {string} account.token
* @param {string} account.refreshToken * @param {string} account.refreshToken
*
* @return {function}
*/ */
export function authenticate({token, refreshToken}) { export function authenticate({token, refreshToken}) {
return (dispatch) => { return (dispatch) =>
return authentication.validateToken({token, refreshToken}) authentication.validateToken({token, refreshToken})
.then(({token, refreshToken}) => .then(({token, refreshToken}) =>
accounts.current({token}) accounts.current({token})
.then((user) => ({ .then((user) => ({
@ -44,11 +46,12 @@ export function authenticate({token, refreshToken}) {
return dispatch(setLocale(user.lang)) return dispatch(setLocale(user.lang))
.then(() => account); .then(() => account);
}); });
};
} }
/** /**
* @param {Account} account * @param {Account} account
*
* @return {function}
*/ */
export function revoke(account) { export function revoke(account) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -56,9 +59,9 @@ export function revoke(account) {
if (getState().accounts.length) { if (getState().accounts.length) {
return dispatch(authenticate(getState().accounts[0])); return dispatch(authenticate(getState().accounts[0]));
} else {
return dispatch(logout());
} }
return dispatch(logout());
}; };
} }
@ -67,6 +70,8 @@ export const ADD = 'accounts:add';
* @api private * @api private
* *
* @param {Account} account * @param {Account} account
*
* @return {object} - action definition
*/ */
export function add(account) { export function add(account) {
return { return {
@ -80,6 +85,8 @@ export const REMOVE = 'accounts:remove';
* @api private * @api private
* *
* @param {Account} account * @param {Account} account
*
* @return {object} - action definition
*/ */
export function remove(account) { export function remove(account) {
return { return {
@ -93,6 +100,8 @@ export const ACTIVATE = 'accounts:activate';
* @api private * @api private
* *
* @param {Account} account * @param {Account} account
*
* @return {object} - action definition
*/ */
export function activate(account) { export function activate(account) {
return { return {
@ -104,6 +113,8 @@ export function activate(account) {
export const UPDATE_TOKEN = 'accounts:updateToken'; export const UPDATE_TOKEN = 'accounts:updateToken';
/** /**
* @param {string} token * @param {string} token
*
* @return {object} - action definition
*/ */
export function updateToken(token) { export function updateToken(token) {
return { return {

View File

@ -29,7 +29,7 @@ export default function refreshTokenMiddleware({dispatch, getState}) {
refreshToken = user.refreshToken; refreshToken = user.refreshToken;
} }
if (!token || isRefreshTokenRequest || req.options.autoRefreshToken === false) { if (!token || req.options.token || isRefreshTokenRequest) {
return req; return req;
} }
@ -49,7 +49,7 @@ export default function refreshTokenMiddleware({dispatch, getState}) {
}, },
catch(resp, req, restart) { catch(resp, req, restart) {
if (resp && resp.status === 401 && req.options.autoRefreshToken !== false) { if (resp && resp.status === 401 && !req.options.token) {
const {user, accounts} = getState(); const {user, accounts} = getState();
const {refreshToken} = accounts.active ? accounts.active : user; const {refreshToken} = accounts.active ? accounts.active : user;

View File

@ -3,15 +3,14 @@ import request from 'services/request';
export default { export default {
/** /**
* @param {object} options * @param {object} options
* @param {object} [options.token] - an optional token to overwrite headers in middleware * @param {object} [options.token] - an optional token to overwrite headers
* @param {bool} [options.autoRefreshToken=true] - disable token auto refresh during request * in middleware and disable token auto-refresh
* *
* @return {Promise<User>} * @return {Promise<User>}
*/ */
current(options = {}) { current(options = {}) {
return request.get('/api/accounts/current', {}, { return request.get('/api/accounts/current', {}, {
token: options.token, token: options.token
autoRefreshToken: options.autoRefreshToken
}); });
}, },

View File

@ -59,7 +59,7 @@ const authentication = {
resolve(); resolve();
}) })
.then(() => accounts.current({token, autoRefreshToken: false})) .then(() => accounts.current({token}))
.then(() => ({token, refreshToken})) .then(() => ({token, refreshToken}))
.catch((resp) => { .catch((resp) => {
if (resp.message === 'Token expired') { if (resp.message === 'Token expired') {

View File

@ -1,6 +1,7 @@
import expect from 'unexpected'; import expect from 'unexpected';
import accounts from 'services/api/accounts'; import accounts from 'services/api/accounts';
import authentication from 'services/api/authentication';
import { authenticate, revoke, add, activate, remove, ADD, REMOVE, ACTIVATE } from 'components/accounts/actions'; import { authenticate, revoke, add, activate, remove, ADD, REMOVE, ACTIVATE } from 'components/accounts/actions';
import { SET_LOCALE } from 'components/i18n/actions'; import { SET_LOCALE } from 'components/i18n/actions';
@ -36,11 +37,18 @@ describe('Accounts actions', () => {
user: {} user: {}
}); });
sinon.stub(authentication, 'validateToken').named('authentication.validateToken');
authentication.validateToken.returns(Promise.resolve({
token: account.token,
refreshToken: account.refreshToken
}));
sinon.stub(accounts, 'current').named('accounts.current'); sinon.stub(accounts, 'current').named('accounts.current');
accounts.current.returns(Promise.resolve(user)); accounts.current.returns(Promise.resolve(user));
}); });
afterEach(() => { afterEach(() => {
authentication.validateToken.restore();
accounts.current.restore(); accounts.current.restore();
}); });

View File

@ -76,10 +76,10 @@ describe('refreshTokenMiddleware', () => {
expect(authentication.requestToken, 'was not called'); expect(authentication.requestToken, 'was not called');
}); });
it('should not apply if options.autoRefreshToken === false', () => { it('should not auto refresh token if options.token specified', () => {
const data = { const data = {
url: 'foo', url: 'foo',
options: {autoRefreshToken: false} options: {token: 'foo'}
}; };
middleware.before(data); middleware.before(data);
@ -257,10 +257,10 @@ describe('refreshTokenMiddleware', () => {
) )
); );
it('should pass the request through if options.autoRefreshToken === false', () => { it('should pass the request through if options.token specified', () => {
const promise = middleware.catch(expiredResponse, { const promise = middleware.catch(expiredResponse, {
options: { options: {
autoRefreshToken: false token: 'foo'
} }
}, restart); }, restart);

View File

@ -21,7 +21,7 @@ describe('authentication api', () => {
expect(authentication.validateToken(validTokens), 'to be fulfilled') expect(authentication.validateToken(validTokens), 'to be fulfilled')
.then(() => { .then(() => {
expect(accounts.current, 'to have a call satisfying', [ expect(accounts.current, 'to have a call satisfying', [
{token: 'foo', autoRefreshToken: false} {token: 'foo'}
]); ]);
}) })
); );