Skip to content

Commit 328aae1

Browse files
committed
STCOR-946: set tenant context based on authentication response with overrideUser parameter on login
1 parent 66132af commit 328aae1

File tree

2 files changed

+72
-16
lines changed

2 files changed

+72
-16
lines changed

src/loginServices.js

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import localforage from 'localforage';
2-
import { config, translations } from 'stripes-config';
2+
import { config, okapi, translations } from 'stripes-config';
33
import rtlDetect from 'rtl-detect';
44
import moment from 'moment';
55
import { loadDayJSLocale } from '@folio/stripes-components';
@@ -400,12 +400,12 @@ function loadResources(store, tenant, userId) {
400400
// in mod-configuration so we can only retrieve them if the user has
401401
// read-permission for configuration entries.
402402
if (canReadConfig(store)) {
403-
const okapi = store.getState()?.okapi;
403+
const okapiObject = store.getState()?.okapi;
404404
promises = [
405-
getLocale(okapi.url, store, tenant),
406-
getUserLocale(okapi.url, store, tenant, userId),
407-
getPlugins(okapi.url, store, tenant),
408-
getBindings(okapi.url, store, tenant),
405+
getLocale(okapiObject.url, store, tenant),
406+
getUserLocale(okapiObject.url, store, tenant, userId),
407+
getPlugins(okapiObject.url, store, tenant),
408+
getBindings(okapiObject.url, store, tenant),
409409
];
410410
}
411411

@@ -594,7 +594,7 @@ export function createOkapiSession(store, tenant, token, data) {
594594
rtExpires: data.tokenExpiration?.refreshTokenExpiration ? new Date(data.tokenExpiration.refreshTokenExpiration).getTime() : Date.now() + (10 * 60 * 1000),
595595
};
596596

597-
const sessionTenant = data.tenant || tenant;
597+
const sessionTenant = data.originalTenantId || data.tenant || tenant;
598598
const okapiSess = {
599599
token,
600600
isAuthenticated: true,
@@ -891,17 +891,16 @@ export function requestLogin(okapiUrl, store, tenant, data) {
891891

892892
/**
893893
* fetchUserWithPerms
894-
* retrieve currently-authenticated user
894+
* retrieve currently-authenticated user data after switching affiliation
895895
* @param {string} okapiUrl
896896
* @param {string} tenant
897897
* @param {string} token
898898
* @param {boolean} rtrIgnore
899-
* @param {boolean} isKeycloak
900899
*
901900
* @returns {Promise} Promise resolving to the response of the request
902901
*/
903-
function fetchUserWithPerms(okapiUrl, tenant, token, rtrIgnore = false, isKeycloak = false) {
904-
const usersPath = isKeycloak ? 'users-keycloak' : 'bl-users';
902+
function fetchUserWithPerms(okapiUrl, tenant, token, rtrIgnore = false) {
903+
const usersPath = okapi.authnUrl ? 'users-keycloak' : 'bl-users';
905904
return fetch(
906905
`${okapiUrl}/${usersPath}/_self?expandPermissions=true&fullPermissions=true`,
907906
{
@@ -911,6 +910,29 @@ function fetchUserWithPerms(okapiUrl, tenant, token, rtrIgnore = false, isKeyclo
911910
);
912911
}
913912

913+
/**
914+
* fetchOverriddenUserWithPerms
915+
* Query string parameter overrideUser is set to true the retrieved shadow user will be used to fetch the real user together with its permissions and service points.
916+
* After fetching process begin a session.
917+
* @param {string} okapiUrl
918+
* @param {redux store} store
919+
* @param {string} tenant
920+
* @param {string} token
921+
*
922+
* @returns {Promise} Promise resolving to the response-body (JSON) of the request
923+
*/
924+
925+
function fetchOverriddenUserWithPerms(okapiUrl, tenant, token, rtrIgnore = false) {
926+
const usersPath = okapi.authnUrl ? 'users-keycloak' : 'bl-users';
927+
return fetch(
928+
`${okapiUrl}/${usersPath}/_self?expandPermissions=true&fullPermissions=true&overrideUser=true`,
929+
{
930+
headers: getHeaders(tenant, token),
931+
rtrIgnore,
932+
},
933+
);
934+
}
935+
914936
/**
915937
* requestUserWithPerms
916938
* retrieve currently-authenticated user, then process the result to begin a session.
@@ -922,8 +944,7 @@ function fetchUserWithPerms(okapiUrl, tenant, token, rtrIgnore = false, isKeyclo
922944
* @returns {Promise} Promise resolving to the response-body (JSON) of the request
923945
*/
924946
export function requestUserWithPerms(okapiUrl, store, tenant, token) {
925-
const isKeycloak = Boolean(store.getState().okapi?.authnUrl);
926-
return fetchUserWithPerms(okapiUrl, tenant, token, !token, isKeycloak)
947+
return fetchOverriddenUserWithPerms(okapiUrl, tenant, token, !token)
927948
.then((resp) => {
928949
if (resp.ok) {
929950
return processOkapiSession(store, tenant, resp, token);
@@ -989,7 +1010,7 @@ export function updateUser(store, data) {
9891010
*/
9901011
export async function updateTenant(okapiConfig, tenant) {
9911012
const okapiSess = await getOkapiSession();
992-
const userWithPermsResponse = await fetchUserWithPerms(okapiConfig.url, tenant, okapiConfig.token, false, Boolean(okapiConfig.authnUrl));
1013+
const userWithPermsResponse = await fetchUserWithPerms(okapiConfig.url, tenant, okapiConfig.token, false);
9931014
const userWithPerms = await userWithPermsResponse.json();
9941015
await localforage.setItem(SESSION_NAME, { ...okapiSess, tenant, ...spreadUserWithPerms(userWithPerms) });
9951016
}

src/loginServices.test.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
validateUser,
2525
IS_LOGGING_OUT,
2626
SESSION_NAME, getStoredTenant,
27-
requestLogin,
27+
requestLogin, requestUserWithPerms,
2828
} from './loginServices';
2929

3030
import {
@@ -63,6 +63,9 @@ jest.mock('stripes-config', () => ({
6363
remus: { name: 'remus', clientId: 'remus-application' },
6464
}
6565
},
66+
okapi: {
67+
authnUrl: 'https://authn.url',
68+
},
6669
translations: {}
6770
}));
6871

@@ -85,7 +88,7 @@ const mockFetchError = (error) => {
8588

8689
// restore default fetch impl
8790
const mockFetchCleanUp = () => {
88-
global.fetch.mockClear();
91+
global.fetch?.mockClear();
8992
delete global.fetch;
9093
};
9194

@@ -765,4 +768,36 @@ describe('unauthorizedPath functions', () => {
765768
);
766769
});
767770
});
771+
772+
describe('requestUserWithPerms', () => {
773+
afterEach(() => {
774+
mockFetchCleanUp();
775+
});
776+
it('should authenticate and create session when valid credentials provided', async () => {
777+
mockFetchSuccess({ tenant:'tenant', originalTenantId:'originalTenantId' });
778+
const mockStore = {
779+
getState: () => ({
780+
okapi: {},
781+
}),
782+
dispatch: jest.fn()
783+
};
784+
785+
await requestUserWithPerms(
786+
'http://okapi-url',
787+
mockStore,
788+
'test-tenant',
789+
'token'
790+
);
791+
792+
expect(global.fetch).toHaveBeenCalledWith('http://okapi-url/users-keycloak/_self?expandPermissions=true&fullPermissions=true&overrideUser=true',
793+
{
794+
headers: expect.objectContaining({
795+
'X-Okapi-Tenant': 'test-tenant',
796+
'X-Okapi-Token': 'token',
797+
'Content-Type': 'application/json',
798+
}),
799+
'rtrIgnore': false
800+
});
801+
});
802+
});
768803
});

0 commit comments

Comments
 (0)