2017-01-04 11:22:46 +05:30
|
|
|
import { routeActions } from 'react-router-redux';
|
|
|
|
|
2016-10-30 17:42:49 +05:30
|
|
|
import authentication from 'services/api/authentication';
|
2017-01-04 11:22:46 +05:30
|
|
|
import { updateUser, setGuest } from 'components/user/actions';
|
2016-11-05 15:41:41 +05:30
|
|
|
import { setLocale } from 'components/i18n/actions';
|
2017-01-31 11:35:36 +05:30
|
|
|
import { setAccountSwitcher } from 'components/auth/actions';
|
2016-12-07 02:36:45 +05:30
|
|
|
import logger from 'services/logger';
|
2017-02-26 17:10:07 +05:30
|
|
|
import { InternalServerError } from 'services/request';
|
2016-10-30 17:42:49 +05:30
|
|
|
|
2017-01-27 11:59:20 +05:30
|
|
|
import {
|
|
|
|
add,
|
|
|
|
remove,
|
|
|
|
activate,
|
|
|
|
reset,
|
|
|
|
updateToken
|
|
|
|
} from 'components/accounts/actions/pure-actions';
|
|
|
|
|
|
|
|
export { updateToken };
|
|
|
|
|
2016-10-30 17:42:49 +05:30
|
|
|
/**
|
|
|
|
* @typedef {object} Account
|
2017-01-12 11:42:56 +05:30
|
|
|
* @property {string} id
|
|
|
|
* @property {string} username
|
|
|
|
* @property {string} email
|
|
|
|
* @property {string} token
|
|
|
|
* @property {string} refreshToken
|
2016-10-30 17:42:49 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {Account|object} account
|
|
|
|
* @param {string} account.token
|
|
|
|
* @param {string} account.refreshToken
|
2016-11-08 12:00:53 +05:30
|
|
|
*
|
|
|
|
* @return {function}
|
2016-10-30 17:42:49 +05:30
|
|
|
*/
|
|
|
|
export function authenticate({token, refreshToken}) {
|
2017-01-31 11:35:36 +05:30
|
|
|
return (dispatch, getState) =>
|
2016-11-08 12:00:53 +05:30
|
|
|
authentication.validateToken({token, refreshToken})
|
2017-02-24 11:20:32 +05:30
|
|
|
.catch((resp = {}) => {
|
2017-02-26 17:10:07 +05:30
|
|
|
if (resp instanceof InternalServerError) {
|
2017-02-24 11:20:32 +05:30
|
|
|
// delegate error recovering to the later logic
|
|
|
|
return Promise.reject(resp);
|
|
|
|
}
|
|
|
|
|
2017-01-06 11:34:14 +05:30
|
|
|
logger.warn('Error validating token during auth', {
|
|
|
|
resp
|
|
|
|
});
|
2016-11-20 15:06:15 +05:30
|
|
|
|
2017-01-06 11:34:14 +05:30
|
|
|
return dispatch(logoutAll())
|
2017-02-24 11:20:32 +05:30
|
|
|
.then(() => Promise.reject(resp));
|
2016-11-20 15:06:15 +05:30
|
|
|
})
|
2017-01-06 11:34:14 +05:30
|
|
|
.then(({token, refreshToken, user}) => ({
|
|
|
|
user: {
|
|
|
|
isGuest: false,
|
|
|
|
...user
|
|
|
|
},
|
|
|
|
account: {
|
|
|
|
id: user.id,
|
|
|
|
username: user.username,
|
|
|
|
email: user.email,
|
|
|
|
token,
|
|
|
|
refreshToken
|
|
|
|
}
|
|
|
|
}))
|
2016-10-30 17:42:49 +05:30
|
|
|
.then(({user, account}) => {
|
2017-01-31 11:35:36 +05:30
|
|
|
const {auth} = getState();
|
|
|
|
|
2016-10-30 17:42:49 +05:30
|
|
|
dispatch(add(account));
|
|
|
|
dispatch(activate(account));
|
2016-12-07 02:36:45 +05:30
|
|
|
dispatch(updateUser(user));
|
|
|
|
|
|
|
|
// TODO: probably should be moved from here, because it is a side effect
|
|
|
|
logger.setUser(user);
|
2016-10-30 17:42:49 +05:30
|
|
|
|
2016-12-06 00:44:38 +05:30
|
|
|
if (!account.refreshToken) {
|
|
|
|
// mark user as stranger (user does not want us to remember his account)
|
|
|
|
sessionStorage.setItem(`stranger${account.id}`, 1);
|
|
|
|
}
|
|
|
|
|
2017-01-31 11:35:36 +05:30
|
|
|
if (auth && auth.oauth && auth.oauth.clientId) {
|
|
|
|
// if we authenticating during oauth, we disable account chooser
|
|
|
|
// because user probably has made his choise now
|
|
|
|
// this may happen, when user registers, logs in or uses account
|
|
|
|
// chooser panel during oauth
|
|
|
|
dispatch(setAccountSwitcher(false));
|
|
|
|
}
|
|
|
|
|
2016-11-05 15:41:41 +05:30
|
|
|
return dispatch(setLocale(user.lang))
|
|
|
|
.then(() => account);
|
2016-10-30 17:42:49 +05:30
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-27 11:59:20 +05:30
|
|
|
* Remove one account from current user's account list
|
|
|
|
*
|
2016-10-30 17:42:49 +05:30
|
|
|
* @param {Account} account
|
2016-11-08 12:00:53 +05:30
|
|
|
*
|
|
|
|
* @return {function}
|
2016-10-30 17:42:49 +05:30
|
|
|
*/
|
|
|
|
export function revoke(account) {
|
|
|
|
return (dispatch, getState) => {
|
2016-11-13 02:01:44 +05:30
|
|
|
const accountToReplace = getState().accounts.available.find(({id}) => id !== account.id);
|
2016-10-30 17:42:49 +05:30
|
|
|
|
2016-11-13 02:01:44 +05:30
|
|
|
if (accountToReplace) {
|
|
|
|
return dispatch(authenticate(accountToReplace))
|
2016-11-15 11:25:15 +05:30
|
|
|
.then(() => {
|
|
|
|
authentication.logout(account);
|
|
|
|
dispatch(remove(account));
|
|
|
|
});
|
2016-10-30 17:42:49 +05:30
|
|
|
}
|
2016-11-08 12:00:53 +05:30
|
|
|
|
2017-01-04 11:22:46 +05:30
|
|
|
return dispatch(logoutAll());
|
2016-10-30 17:42:49 +05:30
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-12-06 00:44:38 +05:30
|
|
|
export function logoutAll() {
|
|
|
|
return (dispatch, getState) => {
|
2017-01-04 11:22:46 +05:30
|
|
|
dispatch(setGuest());
|
|
|
|
|
2016-12-06 00:44:38 +05:30
|
|
|
const {accounts: {available}} = getState();
|
|
|
|
|
|
|
|
available.forEach((account) => authentication.logout(account));
|
|
|
|
|
|
|
|
dispatch(reset());
|
2017-01-04 11:22:46 +05:30
|
|
|
|
|
|
|
dispatch(routeActions.push('/login'));
|
|
|
|
|
|
|
|
return Promise.resolve();
|
2016-12-06 00:44:38 +05:30
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Logouts accounts, that was marked as "do not remember me"
|
|
|
|
*
|
|
|
|
* We detecting foreign accounts by the absence of refreshToken. The account
|
|
|
|
* won't be removed, until key `stranger${account.id}` is present in sessionStorage
|
|
|
|
*
|
|
|
|
* @return {function}
|
|
|
|
*/
|
|
|
|
export function logoutStrangers() {
|
|
|
|
return (dispatch, getState) => {
|
2017-01-12 10:59:39 +05:30
|
|
|
const {accounts: {available, active}} = getState();
|
2016-12-06 00:44:38 +05:30
|
|
|
|
|
|
|
const isStranger = ({refreshToken, id}) => !refreshToken && !sessionStorage.getItem(`stranger${id}`);
|
|
|
|
|
2017-01-12 10:59:39 +05:30
|
|
|
if (available.some(isStranger)) {
|
|
|
|
const accountToReplace = available.filter((account) => !isStranger(account))[0];
|
2016-12-06 00:44:38 +05:30
|
|
|
|
2017-01-12 10:59:39 +05:30
|
|
|
if (accountToReplace) {
|
|
|
|
available.filter(isStranger)
|
|
|
|
.forEach((account) => {
|
|
|
|
dispatch(remove(account));
|
|
|
|
authentication.logout(account);
|
|
|
|
});
|
2016-12-06 00:44:38 +05:30
|
|
|
|
2017-01-12 10:59:39 +05:30
|
|
|
if (isStranger(active)) {
|
|
|
|
return dispatch(authenticate(accountToReplace));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return dispatch(logoutAll());
|
|
|
|
}
|
2016-12-06 00:44:38 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
};
|
|
|
|
}
|