fix: OpenID Connect and Local route rendering

This commit is contained in:
Erik Ziegler 2021-07-02 22:54:26 +02:00
parent f5ecc753f7
commit 3a53479bb7
9 changed files with 50 additions and 67 deletions

View File

@ -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;
}); });
} }

View File

@ -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() {

View File

@ -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,

View File

@ -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}

View File

@ -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

View File

@ -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,

View File

@ -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]);

View File

@ -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}

View File

@ -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