fix: OpenID Connect and Local route rendering
This commit is contained in:
parent
f5ecc753f7
commit
3a53479bb7
@ -186,6 +186,7 @@ export default class ExtensionManager {
|
|||||||
case MODULE_TYPES.SOP_CLASS_HANDLER:
|
case MODULE_TYPES.SOP_CLASS_HANDLER:
|
||||||
case MODULE_TYPES.CONTEXT:
|
case MODULE_TYPES.CONTEXT:
|
||||||
case MODULE_TYPES.LAYOUT_TEMPLATE:
|
case MODULE_TYPES.LAYOUT_TEMPLATE:
|
||||||
|
case MODULE_TYPES.HANGING_PROTOCOL:
|
||||||
// Default for most extension points,
|
// Default for most extension points,
|
||||||
// Just adds each entry ready for consumption by mode.
|
// Just adds each entry ready for consumption by mode.
|
||||||
extensionModule.forEach(element => {
|
extensionModule.forEach(element => {
|
||||||
@ -194,13 +195,6 @@ export default class ExtensionManager {
|
|||||||
] = element;
|
] = element;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case MODULE_TYPES.HANGING_PROTOCOL:
|
|
||||||
extensionModule.forEach(element => {
|
|
||||||
this.modulesMap[
|
|
||||||
`${extensionId}.${moduleType}.${element.name}`
|
|
||||||
] = element;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Module type invalid: ${moduleType}`);
|
throw new Error(`Module type invalid: ${moduleType}`);
|
||||||
}
|
}
|
||||||
@ -306,27 +300,9 @@ export default class ExtensionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_initHangingProtocolModule(extensionModule, extensionId) {
|
_initHangingProtocolModule(extensionModule, extensionId) {
|
||||||
extensionModule.forEach(element => {
|
|
||||||
const namespace = `${extensionId}.${MODULE_TYPES.HANGING_PROTOCOL}.${element.name}`;
|
|
||||||
|
|
||||||
dataSources.forEach(dataSource => {
|
|
||||||
if (dataSource.namespace === namespace) {
|
|
||||||
const dataSourceInstance = element.createDataSource(
|
|
||||||
dataSource.configuration
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.dataSourceMap[dataSource.sourceName]) {
|
|
||||||
this.dataSourceMap[dataSource.sourceName].push(dataSourceInstance);
|
|
||||||
} else {
|
|
||||||
this.dataSourceMap[dataSource.sourceName] = [dataSourceInstance];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
extensionModule.forEach(element => {
|
extensionModule.forEach(element => {
|
||||||
this.modulesMap[
|
this.modulesMap[
|
||||||
`${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`
|
`${extensionId}.${MODULE_TYPES.HANGING_PROTOCOL}.${element.name}`
|
||||||
] = element;
|
] = element;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,9 +37,7 @@ function _getUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _getAuthorizationHeader() {
|
function _getAuthorizationHeader() {
|
||||||
const user = serviceImplementation._getUser();
|
return serviceImplementation._getAuthorizationHeader();
|
||||||
|
|
||||||
return serviceImplementation._getAuthorizationHeader(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _handleUnauthenticated() {
|
function _handleUnauthenticated() {
|
||||||
|
|||||||
@ -88,6 +88,7 @@ export function UserAuthenticationProvider({ children, service }) {
|
|||||||
*
|
*
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
|
// TODO: should this be a useEffect or not?
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (service) {
|
if (service) {
|
||||||
service.setServiceImplementation({
|
service.setServiceImplementation({
|
||||||
@ -100,6 +101,19 @@ export function UserAuthenticationProvider({ children, service }) {
|
|||||||
}
|
}
|
||||||
}, [getState, service, setUser, getUser, reset, set]);
|
}, [getState, service, setUser, getUser, reset, set]);
|
||||||
|
|
||||||
|
// TODO: This may not be correct, but I think we need to set the implementation for the service
|
||||||
|
// immediately when this runs, since otherwise the authentication redirects will fail.
|
||||||
|
// (useEffect only runs after the child components - in this case, routing logic - has failed)
|
||||||
|
if (service) {
|
||||||
|
service.setServiceImplementation({
|
||||||
|
getState,
|
||||||
|
setUser,
|
||||||
|
getUser,
|
||||||
|
reset,
|
||||||
|
set,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
getState,
|
getState,
|
||||||
setUser,
|
setUser,
|
||||||
|
|||||||
@ -79,8 +79,6 @@ function App({ config, defaultExtensions }) {
|
|||||||
let authRoutes = null;
|
let authRoutes = null;
|
||||||
|
|
||||||
if (oidc) {
|
if (oidc) {
|
||||||
UserAuthenticationService.set({ enabled: true });
|
|
||||||
|
|
||||||
authRoutes = (<OpenIdConnectRoutes
|
authRoutes = (<OpenIdConnectRoutes
|
||||||
oidc={oidc}
|
oidc={oidc}
|
||||||
routerBasename={routerBasename}
|
routerBasename={routerBasename}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { MODULE_TYPES } from '@ohif/core'
|
import { MODULE_TYPES } from '@ohif/core'
|
||||||
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import Dropzone from 'react-dropzone'
|
import Dropzone from 'react-dropzone'
|
||||||
import filesToStudies from './filesToStudies'
|
import filesToStudies from './filesToStudies'
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ const getLoadButton = (onDrop, text, isDir) => {
|
|||||||
</Dropzone>)
|
</Dropzone>)
|
||||||
}
|
}
|
||||||
|
|
||||||
function Local(props) {
|
function Local() {
|
||||||
const { history } = props
|
const navigate = useNavigate();
|
||||||
const dropzoneRef = useRef()
|
const dropzoneRef = useRef()
|
||||||
|
|
||||||
// Initializing the dicom local dataSource
|
// Initializing the dicom local dataSource
|
||||||
@ -61,7 +61,7 @@ function Local(props) {
|
|||||||
const onDrop = async (acceptedFiles) => {
|
const onDrop = async (acceptedFiles) => {
|
||||||
const studies = await filesToStudies(acceptedFiles, dataSource)
|
const studies = await filesToStudies(acceptedFiles, dataSource)
|
||||||
// Todo: navigate to work list and let user select a mode
|
// Todo: navigate to work list and let user select a mode
|
||||||
history.push(`/viewer/dicomlocal?StudyInstanceUIDs=${studies[0]}`)
|
navigate(`/viewer/dicomlocal?StudyInstanceUIDs=${studies[0]}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set body style
|
// Set body style
|
||||||
@ -74,7 +74,7 @@ function Local(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropzone ref={dropzoneRef} onDrop={onDrop} noClick>
|
<Dropzone ref={dropzoneRef} onDrop={onDrop} noClick>
|
||||||
{({ getRootProps, getInputProps }) => (
|
{({ getRootProps }) => (
|
||||||
<div {...getRootProps()} style={{ width: '100%', height: '100%' }}>
|
<div {...getRootProps()} style={{ width: '100%', height: '100%' }}>
|
||||||
<div className="h-screen w-screen flex justify-center items-center ">
|
<div className="h-screen w-screen flex justify-center items-center ">
|
||||||
<div className="py-8 px-8 mx-auto bg-secondary-dark shadow-md space-y-2 rounded-lg">
|
<div className="py-8 px-8 mx-auto bg-secondary-dark shadow-md space-y-2 rounded-lg">
|
||||||
@ -107,10 +107,4 @@ function Local(props) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Local.propTypes = {
|
|
||||||
history: PropTypes.shape({
|
|
||||||
push: PropTypes.func,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Local
|
export default Local
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState, useRef } from 'react';
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
import { useParams } from 'react-router';
|
import { useParams, useLocation } from 'react-router';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
// TODO: DicomMetadataStore should be injected?
|
// TODO: DicomMetadataStore should be injected?
|
||||||
import { DicomMetadataStore } from '@ohif/core';
|
import { DicomMetadataStore } from '@ohif/core';
|
||||||
@ -54,7 +54,6 @@ async function defaultRouteInit({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ModeRoute({
|
export default function ModeRoute({
|
||||||
location,
|
|
||||||
mode,
|
mode,
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
extensionManager,
|
extensionManager,
|
||||||
@ -62,6 +61,7 @@ export default function ModeRoute({
|
|||||||
hotkeysManager,
|
hotkeysManager,
|
||||||
}) {
|
}) {
|
||||||
// Parse route params/querystring
|
// Parse route params/querystring
|
||||||
|
const location = useLocation();
|
||||||
const query = useQuery();
|
const query = useQuery();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
||||||
@ -287,14 +287,6 @@ export default function ModeRoute({
|
|||||||
}
|
}
|
||||||
|
|
||||||
ModeRoute.propTypes = {
|
ModeRoute.propTypes = {
|
||||||
// Ref: https://reacttraining.com/react-router/web/api/location
|
|
||||||
location: PropTypes.shape({
|
|
||||||
key: PropTypes.string,
|
|
||||||
pathname: PropTypes.string.isRequired,
|
|
||||||
search: PropTypes.string.isRequired,
|
|
||||||
hash: PropTypes.string.isRequired,
|
|
||||||
//state: PropTypes.object.isRequired,
|
|
||||||
}),
|
|
||||||
mode: PropTypes.object.isRequired,
|
mode: PropTypes.object.isRequired,
|
||||||
dataSourceName: PropTypes.string,
|
dataSourceName: PropTypes.string,
|
||||||
extensionManager: PropTypes.object,
|
extensionManager: PropTypes.object,
|
||||||
|
|||||||
@ -175,12 +175,14 @@ function WorkList({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const search = qs.stringify(queryString, {
|
||||||
|
skipNull: true,
|
||||||
|
skipEmptyString: true,
|
||||||
|
});
|
||||||
|
|
||||||
navigate({
|
navigate({
|
||||||
pathname: '/',
|
pathname: '/',
|
||||||
search: `?${qs.stringify(queryString, {
|
search: search ? `?${search}` : undefined,
|
||||||
skipNull: true,
|
|
||||||
skipEmptyString: true,
|
|
||||||
})}`,
|
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [debouncedFilterValues]);
|
}, [debouncedFilterValues]);
|
||||||
|
|||||||
@ -50,9 +50,8 @@ export default function buildModeRoutes({
|
|||||||
const path = `/${mode.id}/${dataSourceName}`;
|
const path = `/${mode.id}/${dataSourceName}`;
|
||||||
|
|
||||||
// TODO move up.
|
// TODO move up.
|
||||||
const component = ({ location }) => (
|
const children = () => (
|
||||||
<ModeRoute
|
<ModeRoute
|
||||||
location={location}
|
|
||||||
mode={mode}
|
mode={mode}
|
||||||
dataSourceName={dataSourceName}
|
dataSourceName={dataSourceName}
|
||||||
extensionManager={extensionManager}
|
extensionManager={extensionManager}
|
||||||
@ -63,7 +62,7 @@ export default function buildModeRoutes({
|
|||||||
|
|
||||||
routes.push({
|
routes.push({
|
||||||
path,
|
path,
|
||||||
component,
|
children,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,9 +72,8 @@ export default function buildModeRoutes({
|
|||||||
const path = `/${mode.id}`;
|
const path = `/${mode.id}`;
|
||||||
|
|
||||||
// TODO move up.
|
// TODO move up.
|
||||||
const children = ({ location }) => (
|
const children = () => (
|
||||||
<ModeRoute
|
<ModeRoute
|
||||||
location={location}
|
|
||||||
mode={mode}
|
mode={mode}
|
||||||
dataSourceName={defaultDataSourceName}
|
dataSourceName={defaultDataSourceName}
|
||||||
extensionManager={extensionManager}
|
extensionManager={extensionManager}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { Route, Routes, useLocation, useNavigate } from 'react-router';
|
import { Route, Routes, useLocation, useNavigate } from 'react-router';
|
||||||
import CallbackPage from '../routes/CallbackPage';
|
import CallbackPage from '../routes/CallbackPage';
|
||||||
import SignoutCallbackComponent from '../routes/SignoutCallbackComponent';
|
import SignoutCallbackComponent from '../routes/SignoutCallbackComponent';
|
||||||
@ -100,7 +101,10 @@ function OpenIdConnectRoutes({
|
|||||||
UserAuthenticationService
|
UserAuthenticationService
|
||||||
}) {
|
}) {
|
||||||
const userManager = initUserManager(oidc, routerBasename);
|
const userManager = initUserManager(oidc, routerBasename);
|
||||||
const getAuthorizationHeader = (user) => {
|
|
||||||
|
const getAuthorizationHeader = () => {
|
||||||
|
const user = UserAuthenticationService.getUser();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Authorization: `Bearer ${user.access_token}`
|
Authorization: `Bearer ${user.access_token}`
|
||||||
};
|
};
|
||||||
@ -115,10 +119,14 @@ function OpenIdConnectRoutes({
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
UserAuthenticationService.setServiceImplementation({
|
useEffect(() => {
|
||||||
getAuthorizationHeader,
|
UserAuthenticationService.set({ enabled: true });
|
||||||
handleUnauthenticated
|
|
||||||
});
|
UserAuthenticationService.setServiceImplementation({
|
||||||
|
getAuthorizationHeader,
|
||||||
|
handleUnauthenticated
|
||||||
|
});
|
||||||
|
}, [])
|
||||||
|
|
||||||
const oidcAuthority = oidc[0].authority;
|
const oidcAuthority = oidc[0].authority;
|
||||||
|
|
||||||
@ -166,7 +174,10 @@ function OpenIdConnectRoutes({
|
|||||||
|
|
||||||
UserAuthenticationService.setUser(user);
|
UserAuthenticationService.setUser(user);
|
||||||
|
|
||||||
navigate(`${pathname}?${search}`);
|
navigate({
|
||||||
|
pathname,
|
||||||
|
search
|
||||||
|
})
|
||||||
}}/>}
|
}}/>}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user