From c775239f51337f4cb7238ecc60ee0577ce5debfd Mon Sep 17 00:00:00 2001 From: Jakub Niechaj Date: Thu, 19 Oct 2023 18:02:14 +0200 Subject: [PATCH] Add conditional Keycloak provider --- src/App.tsx | 2 +- .../Dialog/RejectKeycloakUserDialog.tsx | 4 +- src/ThreeEditor/js/Storage.js | 53 ++++++++++++++----- .../components/Panels/LoginPanel.tsx | 4 +- src/services/AuthService.tsx | 13 ++--- src/services/GenericContext.ts | 22 ++++++++ src/services/KeycloakAuthService.tsx | 33 ++++++++++-- 7 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a5c6f69c8..213d272de 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -86,11 +86,11 @@ function App() { , , , + , , , , , - , ]}> diff --git a/src/ThreeEditor/components/Dialog/RejectKeycloakUserDialog.tsx b/src/ThreeEditor/components/Dialog/RejectKeycloakUserDialog.tsx index 81001014c..162b39e1a 100644 --- a/src/ThreeEditor/components/Dialog/RejectKeycloakUserDialog.tsx +++ b/src/ThreeEditor/components/Dialog/RejectKeycloakUserDialog.tsx @@ -1,13 +1,13 @@ import { Button } from '@mui/material'; -import { useKeycloak } from 'keycloak-react-web'; +import { useKeycloakAuth } from '../../../services/KeycloakAuthService'; import { ConcreteDialogProps, CustomDialog } from './CustomDialog'; export function RejectKeycloakUserDialog({ onClose, reason }: ConcreteDialogProps & { reason: string }) { - const { keycloak, initialized } = useKeycloak(); + const { keycloak, initialized } = useKeycloakAuth(); return ( ; @@ -80,7 +80,7 @@ const Auth = ({ children }: GenericContextProviderProps) => { const [user, setUser] = useState(load(StorageKey.USER, isAuthUser)); const [reachInterval, setReachInterval] = useState(); const [refreshInterval, setRefreshInterval] = useState(180000); // 3 minutes in ms default interval for refresh token - const { keycloak, initialized } = useKeycloak(); + const { keycloak, initialized } = useKeycloakAuth(); const [keyCloakInterval, setKeyCloakInterval] = useState(); const [isServerReachable, setIsServerReachable] = useState(null); const { enqueueSnackbar } = useSnackbar(); @@ -215,14 +215,7 @@ const Auth = ({ children }: GenericContextProviderProps) => { : err.message }); }); - }, [ - initialized, - keycloak.authenticated, - keycloak.token, - keycloak.tokenParsed?.preferred_username, - kyRef, - open - ]); + }, [initialized, keycloak, kyRef, open]); useEffect(() => { if (initialized && keycloak.authenticated) diff --git a/src/services/GenericContext.ts b/src/services/GenericContext.ts index 4190277a0..7821375ce 100644 --- a/src/services/GenericContext.ts +++ b/src/services/GenericContext.ts @@ -21,3 +21,25 @@ export const createGenericContext = () => { return [useGenericContext, genericContext.Provider] as const; }; + +export const createSubstituteContext = (useSubstituted: () => T) => { + // Create a context with a generic parameter or undefined + const genericContext = createContext(undefined); + + // Check if the value provided to the context is defined or call the substitute + const useSubstituteOrGenericContext = () => { + const contextIsDefined = useContext(genericContext); + + try { + return useSubstituted(); + } catch (e) { + if (!contextIsDefined) { + throw new Error('useSubstituteOrGenericContext must be used within a Provider'); + } + + return contextIsDefined; + } + }; + + return [useSubstituteOrGenericContext, genericContext.Provider] as const; +}; diff --git a/src/services/KeycloakAuthService.tsx b/src/services/KeycloakAuthService.tsx index cfb229531..d37b3d162 100644 --- a/src/services/KeycloakAuthService.tsx +++ b/src/services/KeycloakAuthService.tsx @@ -1,7 +1,8 @@ import Keycloak, { KeycloakInitOptions } from 'keycloak-js'; -import { KeycloakProvider } from 'keycloak-react-web'; +import { KeycloakProvider, useKeycloak } from 'keycloak-react-web'; -import { GenericContextProviderProps } from './GenericContext'; +import { useConfig } from '../config/ConfigService'; +import { createSubstituteContext, GenericContextProviderProps } from './GenericContext'; const authInstance = new Keycloak({ url: `${ @@ -20,12 +21,36 @@ const initOptions = { enableLogging: false } as const satisfies KeycloakInitOptions; -export const KeycloakAuth = ({ children }: GenericContextProviderProps) => { - return ( +export type KeycloakAuthContext = + | { + initialized: false; + keycloak?: Keycloak; + } + | { + initialized: true; + keycloak: Keycloak; + }; + +const [useKeycloakAuth, KeycloakAuthContextProvider] = + createSubstituteContext(useKeycloak); + +const KeycloakAuth = ({ children }: GenericContextProviderProps) => { + const { altAuth } = useConfig(); + + return altAuth ? ( {children} + ) : ( + + {children} + ); }; + +export { KeycloakAuth, useKeycloakAuth };