2023-01-18 12:09:49 +00:00
|
|
|
import type KeycloakAdminClient from "@keycloak/keycloak-admin-client";
|
2021-11-16 11:10:10 +00:00
|
|
|
import { Page } from "@patternfly/react-core";
|
2022-07-14 13:02:28 +00:00
|
|
|
import type Keycloak from "keycloak-js";
|
2023-01-20 14:28:32 +00:00
|
|
|
import { PropsWithChildren, Suspense } from "react";
|
2023-01-18 12:09:49 +00:00
|
|
|
import { ErrorBoundary } from "react-error-boundary";
|
|
|
|
import { HashRouter as Router, Route, Routes } from "react-router-dom";
|
2020-09-25 17:11:25 +00:00
|
|
|
|
2020-10-06 19:25:05 +00:00
|
|
|
import { AlertProvider } from "./components/alert/Alerts";
|
2020-10-01 14:25:29 +00:00
|
|
|
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
|
2021-02-17 21:12:25 +00:00
|
|
|
import { ErrorRenderer } from "./components/error/ErrorRenderer";
|
2023-01-18 12:09:49 +00:00
|
|
|
import { Help } from "./components/help-enabler/HelpHeader";
|
|
|
|
import { KeycloakSpinner } from "./components/keycloak-spinner/KeycloakSpinner";
|
|
|
|
import { AccessContextProvider, useAccess } from "./context/access/Access";
|
2022-08-03 13:15:04 +00:00
|
|
|
import { AdminClientContext } from "./context/auth/AdminClient";
|
2023-01-18 12:09:49 +00:00
|
|
|
import { RealmContextProvider } from "./context/realm-context/RealmContext";
|
|
|
|
import { RealmsProvider } from "./context/RealmsContext";
|
|
|
|
import { ServerInfoProvider } from "./context/server-info/ServerInfoProvider";
|
2021-08-11 11:23:59 +00:00
|
|
|
import { WhoAmIContextProvider } from "./context/whoami/WhoAmI";
|
2023-01-18 12:09:49 +00:00
|
|
|
import { ForbiddenSection } from "./ForbiddenSection";
|
|
|
|
import { SubGroups } from "./groups/SubGroupsContext";
|
|
|
|
import { Header } from "./PageHeader";
|
|
|
|
import { PageNav } from "./PageNav";
|
|
|
|
import { RouteDef, routes } from "./route-config";
|
2020-10-21 11:31:41 +00:00
|
|
|
|
2021-03-17 13:40:19 +00:00
|
|
|
export const mainPageContentId = "kc-main-content-page-container";
|
2020-12-11 17:34:18 +00:00
|
|
|
|
2021-08-11 11:23:59 +00:00
|
|
|
export type AdminClientProps = {
|
2022-07-14 13:02:28 +00:00
|
|
|
keycloak: Keycloak;
|
2021-08-11 11:23:59 +00:00
|
|
|
adminClient: KeycloakAdminClient;
|
2021-01-07 14:56:14 +00:00
|
|
|
};
|
|
|
|
|
2023-01-20 14:28:32 +00:00
|
|
|
const AppContexts = ({
|
2021-08-11 11:23:59 +00:00
|
|
|
children,
|
2022-07-14 13:02:28 +00:00
|
|
|
keycloak,
|
2021-08-11 11:23:59 +00:00
|
|
|
adminClient,
|
2023-01-20 14:28:32 +00:00
|
|
|
}: PropsWithChildren<AdminClientProps>) => (
|
2021-08-11 11:23:59 +00:00
|
|
|
<Router>
|
2023-01-18 12:09:49 +00:00
|
|
|
<AdminClientContext.Provider value={{ keycloak, adminClient }}>
|
|
|
|
<WhoAmIContextProvider>
|
|
|
|
<RealmsProvider>
|
|
|
|
<RealmContextProvider>
|
|
|
|
<AccessContextProvider>
|
|
|
|
<Help>
|
|
|
|
<AlertProvider>
|
|
|
|
<SubGroups>{children}</SubGroups>
|
|
|
|
</AlertProvider>
|
|
|
|
</Help>
|
|
|
|
</AccessContextProvider>
|
|
|
|
</RealmContextProvider>
|
|
|
|
</RealmsProvider>
|
|
|
|
</WhoAmIContextProvider>
|
|
|
|
</AdminClientContext.Provider>
|
2021-08-11 11:23:59 +00:00
|
|
|
</Router>
|
|
|
|
);
|
|
|
|
|
2020-10-21 11:31:41 +00:00
|
|
|
// If someone tries to go directly to a route they don't
|
|
|
|
// have access to, show forbidden page.
|
|
|
|
type SecuredRouteProps = { route: RouteDef };
|
|
|
|
const SecuredRoute = ({ route }: SecuredRouteProps) => {
|
|
|
|
const { hasAccess } = useAccess();
|
2021-08-09 20:20:49 +00:00
|
|
|
const accessAllowed =
|
|
|
|
route.access instanceof Array
|
|
|
|
? hasAccess(...route.access)
|
|
|
|
: hasAccess(route.access);
|
|
|
|
|
2021-11-01 12:29:52 +00:00
|
|
|
if (accessAllowed)
|
2021-10-27 14:15:30 +00:00
|
|
|
return (
|
2021-11-16 11:10:10 +00:00
|
|
|
<Suspense fallback={<KeycloakSpinner />}>
|
2021-10-27 14:15:30 +00:00
|
|
|
<route.component />
|
|
|
|
</Suspense>
|
|
|
|
);
|
2020-10-21 11:31:41 +00:00
|
|
|
|
2022-05-12 08:09:15 +00:00
|
|
|
return <ForbiddenSection permissionNeeded={route.access} />;
|
2020-10-21 11:31:41 +00:00
|
|
|
};
|
|
|
|
|
2022-07-14 13:02:28 +00:00
|
|
|
export const App = ({ keycloak, adminClient }: AdminClientProps) => {
|
2020-08-04 12:59:41 +00:00
|
|
|
return (
|
2022-07-14 13:02:28 +00:00
|
|
|
<AppContexts keycloak={keycloak} adminClient={adminClient}>
|
2021-08-11 11:23:59 +00:00
|
|
|
<Page
|
|
|
|
header={<Header />}
|
|
|
|
isManagedSidebar
|
|
|
|
sidebar={<PageNav />}
|
|
|
|
breadcrumb={<PageBreadCrumbs />}
|
|
|
|
mainContainerId={mainPageContentId}
|
|
|
|
>
|
|
|
|
<ErrorBoundary
|
|
|
|
FallbackComponent={ErrorRenderer}
|
2021-09-30 08:58:48 +00:00
|
|
|
onReset={() =>
|
|
|
|
(window.location.href =
|
|
|
|
window.location.origin + window.location.pathname)
|
|
|
|
}
|
2020-10-08 11:38:25 +00:00
|
|
|
>
|
2022-05-18 08:51:29 +00:00
|
|
|
<ServerInfoProvider>
|
2023-01-18 12:09:49 +00:00
|
|
|
<Routes>
|
2022-08-22 14:29:35 +00:00
|
|
|
{routes.map((route, i) => (
|
2023-01-18 12:09:49 +00:00
|
|
|
<Route
|
2022-08-22 14:29:35 +00:00
|
|
|
key={i}
|
|
|
|
path={route.path}
|
2023-01-18 12:09:49 +00:00
|
|
|
element={<SecuredRoute route={route} />}
|
|
|
|
/>
|
2022-08-22 14:29:35 +00:00
|
|
|
))}
|
2023-01-18 12:09:49 +00:00
|
|
|
</Routes>
|
2022-05-18 08:51:29 +00:00
|
|
|
</ServerInfoProvider>
|
2021-08-11 11:23:59 +00:00
|
|
|
</ErrorBoundary>
|
|
|
|
</Page>
|
2020-10-08 11:38:25 +00:00
|
|
|
</AppContexts>
|
2020-08-04 12:59:41 +00:00
|
|
|
);
|
|
|
|
};
|