feat: Support for OpenID Connect (#2431)
* feat: Add OpenID Connect support, speed up docker rebuilds * fix: Switch Google Cloud API URL to v1 * chore: Remove redux-oidc and use our own components instead
This commit is contained in:
1 parent
5643f8f6d2
commit
e7b32cc51e
50 files changed
+2746
-2109
No files matched your search
@@ -41,6 +41,7 @@
|
||||
"dicomweb-client": "^0.6.0",
|
||||
"isomorphic-base64": "^1.0.2",
|
||||
"lodash.merge": "^4.6.1",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"moment": "^2.24.0",
|
||||
"mousetrap": "^1.6.3",
|
||||
"query-string": "^6.14.0",
|
||||
|
||||
@@ -10,7 +10,7 @@ import user from '../user';
|
||||
* @param {string|function} [server.requestOptions.auth]
|
||||
* @returns {Object} { Authorization }
|
||||
*/
|
||||
export default function getAuthorizationHeader({ requestOptions } = {}) {
|
||||
export default function getAuthorizationHeader({ requestOptions } = {}, user) {
|
||||
const headers = {};
|
||||
|
||||
// Check for OHIF.user since this can also be run on the server
|
||||
|
||||
@@ -64,11 +64,11 @@ describe('getAuthorizationHeader', () => {
|
||||
it('should return an Authorization with accessToken when server is not defined and there is an accessToken', () => {
|
||||
user.getAccessToken.mockImplementationOnce(() => 'MOCKED_TOKEN');
|
||||
|
||||
const authentication = getAuthorizationHeader({});
|
||||
const exptecteHeaderBasedOnUserAccessToekn = {
|
||||
const authentication = getAuthorizationHeader({}, user);
|
||||
const expectedHeaderBasedOnUserAccessToken = {
|
||||
Authorization: 'Bearer MOCKED_TOKEN',
|
||||
};
|
||||
|
||||
expect(authentication).toEqual(exptecteHeaderBasedOnUserAccessToekn);
|
||||
expect(authentication).toEqual(expectedHeaderBasedOnUserAccessToken);
|
||||
});
|
||||
});
|
||||
@@ -439,7 +439,7 @@ class MetadataProvider {
|
||||
|
||||
_getUIDsFromImageID(imageId) {
|
||||
if (imageId.includes('wadors:')) {
|
||||
const strippedImageId = imageId.split('studies/')[1];
|
||||
const strippedImageId = imageId.split('/studies/')[1];
|
||||
const splitImageId = strippedImageId.split('/');
|
||||
|
||||
return {
|
||||
|
||||
@@ -277,13 +277,16 @@ export default class ExtensionManager {
|
||||
};
|
||||
|
||||
_initDataSourcesModule(extensionModule, extensionId, dataSources = []) {
|
||||
const { UserAuthenticationService } = this._servicesManager.services;
|
||||
|
||||
extensionModule.forEach(element => {
|
||||
const namespace = `${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`;
|
||||
|
||||
dataSources.forEach(dataSource => {
|
||||
if (dataSource.namespace === namespace) {
|
||||
const dataSourceInstance = element.createDataSource(
|
||||
dataSource.configuration
|
||||
dataSource.configuration,
|
||||
UserAuthenticationService
|
||||
);
|
||||
|
||||
if (this.dataSourceMap[dataSource.sourceName]) {
|
||||
|
||||
@@ -15,6 +15,10 @@ describe('ExtensionManager.js', () => {
|
||||
};
|
||||
servicesManager = {
|
||||
registerService: jest.fn(),
|
||||
services: {
|
||||
// Required for DataSource Module initiation
|
||||
UserAuthenticationService: jest.fn(),
|
||||
},
|
||||
};
|
||||
appConfig = {
|
||||
testing: true,
|
||||
@@ -100,7 +104,6 @@ describe('ExtensionManager.js', () => {
|
||||
extensionManager.registerExtension(undefinedExtension);
|
||||
}).toThrow('Attempting to register a null/undefined extension.');
|
||||
|
||||
|
||||
expect(() => {
|
||||
extensionManager.registerExtension(nullExtension);
|
||||
}).toThrow('Attempting to register a null/undefined extension.');
|
||||
@@ -185,7 +188,7 @@ describe('ExtensionManager.js', () => {
|
||||
hotkeysManager: undefined,
|
||||
appConfig,
|
||||
configuration: extensionConfiguration,
|
||||
extensionManager
|
||||
extensionManager,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -220,7 +223,7 @@ describe('ExtensionManager.js', () => {
|
||||
},
|
||||
getContextModule: () => {
|
||||
return [{}];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
extensionManager.registerExtension(extension);
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
pubSubServiceInterface,
|
||||
UserAuthenticationService,
|
||||
} from './services';
|
||||
|
||||
import IWebApiDataSource from './DataSources/IWebApiDataSource';
|
||||
@@ -66,6 +67,7 @@ const OHIF = {
|
||||
ToolBarService, // TODO: TYPO
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
UserAuthenticationService,
|
||||
IWebApiDataSource,
|
||||
DicomMetadataStore,
|
||||
pubSubServiceInterface,
|
||||
@@ -101,6 +103,7 @@ export {
|
||||
ToolBarService,
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
UserAuthenticationService,
|
||||
IWebApiDataSource,
|
||||
DicomMetadataStore,
|
||||
pubSubServiceInterface,
|
||||
|
||||
@@ -34,9 +34,10 @@ describe('Top level exports', () => {
|
||||
'ToolBarService',
|
||||
'ViewportGridService',
|
||||
'HangingProtocolService',
|
||||
'UserAuthenticationService',
|
||||
'IWebApiDataSource',
|
||||
'DicomMetadataStore',
|
||||
'pubSubServiceInterface'
|
||||
'pubSubServiceInterface',
|
||||
].sort();
|
||||
|
||||
const exports = Object.keys(OHIF).sort();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cloneDeep } from 'lodash';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
|
||||
import sortBy from '../../utils/sortBy.js';
|
||||
import ProtocolEngine from './ProtocolEngine';
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
const name = 'UserAuthenticationService';
|
||||
|
||||
const publicAPI = {
|
||||
name,
|
||||
getState: _getState,
|
||||
setUser: _setUser,
|
||||
getUser: _getUser,
|
||||
getAuthorizationHeader: _getAuthorizationHeader,
|
||||
handleUnauthenticated: _handleUnauthenticated,
|
||||
setServiceImplementation,
|
||||
reset: _reset,
|
||||
set: _set,
|
||||
};
|
||||
|
||||
const serviceImplementation = {
|
||||
_getState: () => console.warn('getState() NOT IMPLEMENTED'),
|
||||
_setUser: () => console.warn('_setUser() NOT IMPLEMENTED'),
|
||||
_getUser: () => console.warn('_setUser() NOT IMPLEMENTED'),
|
||||
_getAuthorizationHeader: () =>
|
||||
console.warn('_getAuthorizationHeader() NOT IMPLEMENTED'),
|
||||
_handleUnauthenticated: () =>
|
||||
console.warn('_handleUnauthenticated() NOT IMPLEMENTED'),
|
||||
_reset: () => console.warn('reset() NOT IMPLEMENTED'),
|
||||
_set: () => console.warn('set() NOT IMPLEMENTED'),
|
||||
};
|
||||
|
||||
function _getState() {
|
||||
return serviceImplementation._getState();
|
||||
}
|
||||
|
||||
function _setUser(user) {
|
||||
return serviceImplementation._setUser(user);
|
||||
}
|
||||
|
||||
function _getUser() {
|
||||
return serviceImplementation._getUser();
|
||||
}
|
||||
|
||||
function _getAuthorizationHeader() {
|
||||
const user = serviceImplementation._getUser();
|
||||
|
||||
return serviceImplementation._getAuthorizationHeader(user);
|
||||
}
|
||||
|
||||
function _handleUnauthenticated() {
|
||||
return serviceImplementation._handleUnauthenticated();
|
||||
}
|
||||
|
||||
function _set(state) {
|
||||
return serviceImplementation._set(state);
|
||||
}
|
||||
|
||||
function _reset() {
|
||||
return serviceImplementation._reset({});
|
||||
}
|
||||
|
||||
function setServiceImplementation({
|
||||
getState: getStateImplementation,
|
||||
setUser: setUserImplementation,
|
||||
getUser: getUserImplementation,
|
||||
getAuthorizationHeader: getAuthorizationHeaderImplementation,
|
||||
handleUnauthenticated: handleUnauthenticatedImplementation,
|
||||
reset: resetImplementation,
|
||||
set: setImplementation,
|
||||
}) {
|
||||
if (getStateImplementation) {
|
||||
serviceImplementation._getState = getStateImplementation;
|
||||
}
|
||||
if (setUserImplementation) {
|
||||
serviceImplementation._setUser = setUserImplementation;
|
||||
}
|
||||
if (getUserImplementation) {
|
||||
serviceImplementation._getUser = getUserImplementation;
|
||||
}
|
||||
if (getAuthorizationHeaderImplementation) {
|
||||
serviceImplementation._getAuthorizationHeader = getAuthorizationHeaderImplementation;
|
||||
}
|
||||
if (handleUnauthenticatedImplementation) {
|
||||
serviceImplementation._handleUnauthenticated = handleUnauthenticatedImplementation;
|
||||
}
|
||||
if (resetImplementation) {
|
||||
serviceImplementation._reset = resetImplementation;
|
||||
}
|
||||
if (setImplementation) {
|
||||
serviceImplementation._set = setImplementation;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
create: ({ configuration = {} }) => {
|
||||
return publicAPI;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
import UserAuthenticationService from './UserAuthenticationService';
|
||||
|
||||
export default UserAuthenticationService;
|
||||
@@ -11,6 +11,7 @@ import ViewportGridService from './ViewportGridService';
|
||||
import CineService from './CineService';
|
||||
import HangingProtocolService from './HangingProtocolService';
|
||||
import pubSubServiceInterface from './_shared/pubSubServiceInterface';
|
||||
import UserAuthenticationService from './UserAuthenticationService';
|
||||
|
||||
export {
|
||||
MeasurementService,
|
||||
@@ -26,4 +27,5 @@ export {
|
||||
HangingProtocolService,
|
||||
CineService,
|
||||
pubSubServiceInterface,
|
||||
UserAuthenticationService,
|
||||
};
|
||||
Reference in new issue
Block a user