/* global WP_DEFINE_IS_NODE */
import {
SET_AUTH_TOKENS,
SET_INITIAL_USER_STATE,
CHANGE_INITIAL_USER_STATE,
SET_USER_PERMISSION_STATE,
} from '../actions/authenticationActions';
import { getAccountType } from '../util/userPermissionStateUtil';
/**
* Object that maps JWT clauses to their corresponding property names in an account entity
* from the API. This is used to have a consistent API to get account information from the
* userAccountSelector
*/
export const JWT_CLAUSE_MAP = {
sub: 'id',
preferred_username: 'userName',
name: 'name',
role: 'roles',
zoneinfo: 'timeZoneId',
group_id: 'groupId',
account_state: 'accountState',
member_type: 'memberType',
};
export const JWT_CLAUSE_MAP_ID_TOKEN = {
email: 'email',
ua: 'ua',
mps: 'mps',
};
const authenticationReducer = (
authState = {
/**
* The JWT access token (if the user is logged in)
* This will be removed in the initial state sent to the client, because the client
* will get its own access token using the implicit auth flow
*/
accessToken: null,
/**
* The JWT identity token (if the user is logged in)
* This will be removed in the initial state sent to the client, because the client
* will get its own access token using the implicit auth flow
*/
idToken: null,
/**
* An object containing the decoded clauses in the JWT access token (if the user is logged in).
* This information will be available as initial state to the client. This is to make sure
* the clauses in the token are immediately available on the client, without having to wait
* for the implicit auth flow to complete. For that reason, some technical clauses that are
* specifically meant for the server token are not included in this object (like nbf, issuer,
* exp)
*
* __PLEASE NOTE: __ As we want a single source of truth for account information, it is best
* not to use this state directly. Instead, use the userAccountSelector available in the
* `reducers` folder.
*/
userInfo: null,
},
action,
) => {
switch (action.type) {
case SET_AUTH_TOKENS: {
const { idToken, accessToken, decodedAccessToken, decodedIdToken } = action.payload;
const userInfo = authState.userInfo || {};
Object.keys(JWT_CLAUSE_MAP).forEach(
clause => (userInfo[clause] = decodedAccessToken[clause]),
);
Object.keys(JWT_CLAUSE_MAP_ID_TOKEN).forEach(
clause => (userInfo[clause] = decodedIdToken[clause]),
);
return {
...authState,
accessToken,
idToken,
userInfo,
userPermissionState: {
// eslint-disable-next-line no-underscore-dangle
...authState.userPermissionState,
accountState: userInfo.account_state,
},
};
}
case SET_INITIAL_USER_STATE:
case CHANGE_INITIAL_USER_STATE: {
const prevUserInfo = authState.userInfo || {};
return {
...authState,
userInfo: {
...prevUserInfo,
initialUserState: action.payload,
},
};
}
case SET_USER_PERMISSION_STATE: {
const { accountState, roles, userId } = action.payload;
return {
...authState,
userPermissionState: {
userId,
accountState,
roles,
subscriptionType: getAccountType(accountState),
},
};
}
default:
return authState;
}
};
export default authenticationReducer;