|
- import { ConfigProvider, Result, Spin, theme } from 'antd'
- import { useCallback, useMemo } from 'react'
- import './App.css'
- import {
- buildKeycloakAuthorizationUrl,
- getKeycloakClientConfig,
- authenticatedFetch,
- logout,
- oidcStateStorageKey,
- submitKeycloakLogout,
- storeAuthTokenSet,
- } from './auth/authContracts'
- import { useOidcSession } from './auth/useOidcSession'
- import { WorkspaceShell } from './workspace/WorkspaceShell'
- import { workspaceThemeTokens } from './workspace/workspaceContracts'
-
- function App() {
- const session = useOidcSession()
- const config = useMemo(() => getKeycloakClientConfig(), [])
-
- const handleLogout = useCallback(async () => {
- const idToken = session.status === 'authenticated' ? (session.tokens.idToken ?? '') : ''
- const accessToken = session.status === 'authenticated' ? session.tokens.accessToken : undefined
- await logout(idToken, accessToken)
- const state = crypto.randomUUID()
- window.sessionStorage.setItem(oidcStateStorageKey, state)
- if (idToken) {
- submitKeycloakLogout(config, idToken, window.location.origin)
- return
- }
-
- window.location.assign(
- buildKeycloakAuthorizationUrl(config, state, crypto.randomUUID()).toString(),
- )
- }, [session, config])
-
- const adminFetch = useCallback(
- async (input: RequestInfo | URL, init: RequestInit = {}) => {
- if (session.status !== 'authenticated') {
- throw new Error('Admin request requires an authenticated session')
- }
-
- return authenticatedFetch(input, init, config, session.tokens, storeAuthTokenSet)
- },
- [config, session],
- )
-
- const content =
- session.status === 'authenticated' ? (
- <WorkspaceShell user={session.user} onLogout={handleLogout} adminFetch={adminFetch} />
- ) : session.status === 'error' ? (
- <Result status="warning" title={session.error} />
- ) : (
- <div className="app-auth-state" aria-live="polite">
- <Spin />
- </div>
- )
-
- return (
- <ConfigProvider
- theme={{
- algorithm: theme.compactAlgorithm,
- token: workspaceThemeTokens,
- components: {
- Layout: {
- headerBg: '#FFFFFF',
- siderBg: '#FFFFFF',
- },
- Table: {
- cellPaddingBlockSM: 6,
- cellPaddingInlineSM: 8,
- },
- },
- }}
- >
- <div className="app-shell">
- {content}
- </div>
- </ConfigProvider>
- )
- }
-
- export default App
|