Create whoami context (#136)

* Fix conflicts

* Fix formatting

* Get tests to pass

* Fix conflict again
This commit is contained in:
Stan Silvert 2020-10-02 02:47:32 -04:00 committed by GitHub
parent 2fa8855bf4
commit f800e000be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 292 additions and 165 deletions

View file

@ -7,6 +7,7 @@ import { PageNav } from "./PageNav";
import { Help } from "./components/help-enabler/HelpHeader"; import { Help } from "./components/help-enabler/HelpHeader";
import { RealmContextProvider } from "./components/realm-context/RealmContext"; import { RealmContextProvider } from "./components/realm-context/RealmContext";
import { WhoAmIContextProvider } from "./whoami/WhoAmI";
import { routes } from "./route-config"; import { routes } from "./route-config";
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs"; import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
@ -14,22 +15,24 @@ import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
export const App = () => { export const App = () => {
return ( return (
<Router> <Router>
<RealmContextProvider> <WhoAmIContextProvider>
<Help> <RealmContextProvider>
<Page <Help>
header={<Header />} <Page
isManagedSidebar header={<Header />}
sidebar={<PageNav />} isManagedSidebar
breadcrumb={<PageBreadCrumbs />} sidebar={<PageNav />}
> breadcrumb={<PageBreadCrumbs />}
<Switch> >
{routes(() => {}).map((route, i) => ( <Switch>
<Route key={i} {...route} exact /> {routes(() => {}).map((route, i) => (
))} <Route key={i} {...route} exact />
</Switch> ))}
</Page> </Switch>
</Help> </Page>
</RealmContextProvider> </Help>
</RealmContextProvider>
</WhoAmIContextProvider>
</Router> </Router>
); );
}; };

View file

@ -15,6 +15,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { HelpIcon } from "@patternfly/react-icons"; import { HelpIcon } from "@patternfly/react-icons";
import { KeycloakContext } from "./auth/KeycloakContext"; import { KeycloakContext } from "./auth/KeycloakContext";
import { WhoAmIContext } from "./whoami/WhoAmI";
import { HelpHeader } from "./components/help-enabler/HelpHeader"; import { HelpHeader } from "./components/help-enabler/HelpHeader";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@ -134,6 +135,7 @@ const KebabDropdown = () => {
const UserDropdown = () => { const UserDropdown = () => {
const keycloak = useContext(KeycloakContext); const keycloak = useContext(KeycloakContext);
const whoami = useContext(WhoAmIContext);
const [isDropdownOpen, setDropdownOpen] = useState(false); const [isDropdownOpen, setDropdownOpen] = useState(false);
const onDropdownToggle = () => { const onDropdownToggle = () => {
@ -147,7 +149,7 @@ const UserDropdown = () => {
isOpen={isDropdownOpen} isOpen={isDropdownOpen}
toggle={ toggle={
<DropdownToggle onToggle={onDropdownToggle}> <DropdownToggle onToggle={onDropdownToggle}>
{keycloak?.loggedInUser} {whoami.getDisplayName()}
</DropdownToggle> </DropdownToggle>
} }
dropdownItems={userDropdownItems} dropdownItems={userDropdownItems}

View file

@ -6,7 +6,7 @@ Object {
"baseElement": <body> "baseElement": <body>
<div> <div>
<table <table
aria-label="clientList" aria-label="Client list"
class="pf-c-table pf-m-grid-md pf-m-compact" class="pf-c-table pf-m-grid-md pf-m-compact"
data-ouia-component-id="OUIA-Generated-Table-1" data-ouia-component-id="OUIA-Generated-Table-1"
data-ouia-component-type="PF4/Table" data-ouia-component-type="PF4/Table"
@ -20,34 +20,34 @@ Object {
<th <th
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
scope="col" scope="col"
> >
clientID Client ID
</th> </th>
<th <th
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
scope="col" scope="col"
> >
type Type
</th> </th>
<th <th
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
scope="col" scope="col"
> >
description Description
</th> </th>
<th <th
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
scope="col" scope="col"
> >
homeURL Home URL
</th> </th>
<td <td
class="" class=""
@ -68,7 +68,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/767756c2-21f8-431c-9f4b-edf30654d653" href="/clients/767756c2-21f8-431c-9f4b-edf30654d653"
@ -79,21 +79,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -167,7 +167,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/337dc87b-e08d-409e-aaac-6ab7df4b925b" href="/clients/337dc87b-e08d-409e-aaac-6ab7df4b925b"
@ -178,21 +178,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -266,7 +266,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/60d59afe-7926-4c22-b829-798125793ef5" href="/clients/60d59afe-7926-4c22-b829-798125793ef5"
@ -277,21 +277,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -339,7 +339,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/c2d74093-2b8c-4ecb-870f-c7358ff48237" href="/clients/c2d74093-2b8c-4ecb-870f-c7358ff48237"
@ -350,21 +350,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -412,7 +412,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/66135023-e667-4864-b1f3-f87e805fabc2" href="/clients/66135023-e667-4864-b1f3-f87e805fabc2"
@ -423,19 +423,19 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
/> />
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -483,7 +483,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/324f4182-d302-44f8-ac8a-149eaa29dc90" href="/clients/324f4182-d302-44f8-ac8a-149eaa29dc90"
@ -494,21 +494,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -582,7 +582,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/fb45882b-4d85-4f40-920e-6a68298d36d0" href="/clients/fb45882b-4d85-4f40-920e-6a68298d36d0"
@ -593,19 +593,19 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
/> />
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -653,7 +653,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/9ed60e41-d794-4046-842f-3247bf32f5ce" href="/clients/9ed60e41-d794-4046-842f-3247bf32f5ce"
@ -664,21 +664,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -754,7 +754,7 @@ Object {
</body>, </body>,
"container": <div> "container": <div>
<table <table
aria-label="clientList" aria-label="Client list"
class="pf-c-table pf-m-grid-md pf-m-compact" class="pf-c-table pf-m-grid-md pf-m-compact"
data-ouia-component-id="OUIA-Generated-Table-1" data-ouia-component-id="OUIA-Generated-Table-1"
data-ouia-component-type="PF4/Table" data-ouia-component-type="PF4/Table"
@ -768,34 +768,34 @@ Object {
<th <th
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
scope="col" scope="col"
> >
clientID Client ID
</th> </th>
<th <th
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
scope="col" scope="col"
> >
type Type
</th> </th>
<th <th
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
scope="col" scope="col"
> >
description Description
</th> </th>
<th <th
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
scope="col" scope="col"
> >
homeURL Home URL
</th> </th>
<td <td
class="" class=""
@ -816,7 +816,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/767756c2-21f8-431c-9f4b-edf30654d653" href="/clients/767756c2-21f8-431c-9f4b-edf30654d653"
@ -827,21 +827,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -915,7 +915,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/337dc87b-e08d-409e-aaac-6ab7df4b925b" href="/clients/337dc87b-e08d-409e-aaac-6ab7df4b925b"
@ -926,21 +926,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -1014,7 +1014,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/60d59afe-7926-4c22-b829-798125793ef5" href="/clients/60d59afe-7926-4c22-b829-798125793ef5"
@ -1025,21 +1025,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -1087,7 +1087,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/c2d74093-2b8c-4ecb-870f-c7358ff48237" href="/clients/c2d74093-2b8c-4ecb-870f-c7358ff48237"
@ -1098,21 +1098,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -1160,7 +1160,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/66135023-e667-4864-b1f3-f87e805fabc2" href="/clients/66135023-e667-4864-b1f3-f87e805fabc2"
@ -1171,19 +1171,19 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
/> />
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -1231,7 +1231,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/324f4182-d302-44f8-ac8a-149eaa29dc90" href="/clients/324f4182-d302-44f8-ac8a-149eaa29dc90"
@ -1242,21 +1242,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"
@ -1330,7 +1330,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/fb45882b-4d85-4f40-920e-6a68298d36d0" href="/clients/fb45882b-4d85-4f40-920e-6a68298d36d0"
@ -1341,19 +1341,19 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
/> />
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
</td> </td>
@ -1401,7 +1401,7 @@ Object {
<td <td
class="" class=""
data-key="0" data-key="0"
data-label="clientID" data-label="Client ID"
> >
<a <a
href="/clients/9ed60e41-d794-4046-842f-3247bf32f5ce" href="/clients/9ed60e41-d794-4046-842f-3247bf32f5ce"
@ -1412,21 +1412,21 @@ Object {
<td <td
class="" class=""
data-key="1" data-key="1"
data-label="type" data-label="Type"
> >
openid-connect openid-connect
</td> </td>
<td <td
class="" class=""
data-key="2" data-key="2"
data-label="description" data-label="Description"
> >
</td> </td>
<td <td
class="" class=""
data-key="3" data-key="3"
data-label="homeURL" data-label="Home URL"
> >
<a <a
aria-disabled="false" aria-disabled="false"

View file

@ -35,7 +35,7 @@ exports[`BreadCrumbs tests couple of crumbs 1`] = `
<span <span
key="/" key="/"
> >
home Home
</span> </span>
</a> </a>
</LinkAnchor> </LinkAnchor>
@ -81,7 +81,7 @@ exports[`BreadCrumbs tests couple of crumbs 1`] = `
<span <span
key="/add-client" key="/add-client"
> >
createClient Create client
</span> </span>
</li> </li>
</BreadcrumbItem> </BreadcrumbItem>

View file

@ -1,7 +1,8 @@
import React, { useState } from "react"; import React, { useState, useContext } from "react";
import { WhoAmIContext } from "../../whoami/WhoAmI";
export const RealmContext = React.createContext({ export const RealmContext = React.createContext({
realm: "master", realm: "",
setRealm: (realm: string) => {}, setRealm: (realm: string) => {},
}); });
@ -10,7 +11,8 @@ type RealmContextProviderProps = { children: React.ReactNode };
export const RealmContextProvider = ({ export const RealmContextProvider = ({
children, children,
}: RealmContextProviderProps) => { }: RealmContextProviderProps) => {
const [realm, setRealm] = useState("master"); const homeRealm = useContext(WhoAmIContext).getHomeRealm();
const [realm, setRealm] = useState(homeRealm);
return ( return (
<RealmContext.Provider value={{ realm, setRealm }}> <RealmContext.Provider value={{ realm, setRealm }}>

View file

@ -16,6 +16,7 @@ import { CheckIcon } from "@patternfly/react-icons";
import { RealmRepresentation } from "../../realm/models/Realm"; import { RealmRepresentation } from "../../realm/models/Realm";
import { RealmContext } from "../realm-context/RealmContext"; import { RealmContext } from "../realm-context/RealmContext";
import { WhoAmIContext } from "../../whoami/WhoAmI";
import "./realm-selector.css"; import "./realm-selector.css";
@ -25,6 +26,7 @@ type RealmSelectorProps = {
export const RealmSelector = ({ realmList }: RealmSelectorProps) => { export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
const { realm, setRealm } = useContext(RealmContext); const { realm, setRealm } = useContext(RealmContext);
const whoami = useContext(WhoAmIContext);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [filteredItems, setFilteredItems] = useState(realmList); const [filteredItems, setFilteredItems] = useState(realmList);
@ -77,6 +79,19 @@ export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
</DropdownItem> </DropdownItem>
)); ));
const addRealmComponent = (
<React.Fragment key="Add Realm">
{whoami.canCreateRealm() && (
<>
<Divider key="divider" />
<DropdownItem key="add">
<AddRealm />
</DropdownItem>
</>
)}
</React.Fragment>
);
return ( return (
<> <>
{realmList.length > 5 && ( {realmList.length > 5 && (
@ -119,13 +134,7 @@ export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
{toUpperCase(realm)} {toUpperCase(realm)}
</DropdownToggle> </DropdownToggle>
} }
dropdownItems={[ dropdownItems={[...dropdownItems, addRealmComponent]}
...dropdownItems,
<Divider key="divider" />,
<DropdownItem key="add">
<AddRealm />
</DropdownItem>,
]}
/> />
)} )}
</> </>

View file

@ -23,10 +23,7 @@ exports[`renders realm selector 1`] = `
value="another" value="another"
/> />
</DropdownItem>, </DropdownItem>,
<Divider />, <React.Fragment />,
<DropdownItem>
<AddRealm />
</DropdownItem>,
] ]
} }
id="realm-select" id="realm-select"
@ -54,10 +51,7 @@ exports[`renders realm selector 1`] = `
value="another" value="another"
/> />
</DropdownItem>, </DropdownItem>,
<Divider />, <React.Fragment />,
<DropdownItem>
<AddRealm />
</DropdownItem>,
] ]
} }
id="realm-select" id="realm-select"
@ -160,29 +154,6 @@ exports[`renders realm selector 1`] = `
</div> </div>
</a> </a>
</li> </li>
<hr
class="pf-c-divider"
index="1"
/>
<li
role="menuitem"
>
<a
aria-disabled="false"
class="pf-c-dropdown__menu-item"
tabindex="-1"
>
<div
aria-disabled="false"
class="pf-c-button pf-m-primary pf-m-block"
data-ouia-component-id="OUIA-Generated-Button-primary-1"
data-ouia-component-type="PF4/Button"
data-ouia-safe="true"
>
Create Realm
</div>
</a>
</li>
</ul> </ul>
</div>, </div>,
} }
@ -268,29 +239,6 @@ exports[`renders realm selector 1`] = `
</div> </div>
</a> </a>
</li> </li>
<hr
class="pf-c-divider"
index="1"
/>
<li
role="menuitem"
>
<a
aria-disabled="false"
class="pf-c-dropdown__menu-item"
tabindex="-1"
>
<div
aria-disabled="false"
class="pf-c-button pf-m-primary pf-m-block"
data-ouia-component-id="OUIA-Generated-Button-primary-1"
data-ouia-component-type="PF4/Button"
data-ouia-safe="true"
>
Create Realm
</div>
</a>
</li>
</ul> </ul>
</div>, </div>,
} }

78
src/whoami/WhoAmI.tsx Normal file
View file

@ -0,0 +1,78 @@
import React, { useContext } from "react";
import i18n from "../i18n";
import WhoAmIRepresentation from "./who-am-i-model";
import { HttpClientContext } from "../http-service/HttpClientContext";
import { KeycloakContext } from "../auth/KeycloakContext";
import { DataLoader } from "../components/data-loader/DataLoader";
export class WhoAmI {
constructor(
private homeRealm?: string | undefined,
private me?: WhoAmIRepresentation | undefined
) {
if (this.me !== undefined && this.me.locale) {
i18n.changeLanguage(this.me.locale, (error) => {
if (error) console.log("Unable to set locale to " + this.me?.locale);
});
}
}
public getDisplayName(): string {
if (this.me === undefined) return "";
return this.me.displayName;
}
/**
* Return the realm I am signed in to.
*/
public getHomeRealm(): string {
let realm: string | undefined = this.homeRealm;
if (realm === undefined) realm = this.me?.realm;
if (realm === undefined) realm = "master"; // this really can't happen in the real world
return realm;
}
public canCreateRealm(): boolean {
return this.me !== undefined && this.me.createRealm;
}
public getRealmAccess(): Readonly<{ [key: string]: ReadonlyArray<string> }> {
if (this.me === undefined) return {};
return this.me.realm_access;
}
}
export const WhoAmIContext = React.createContext(new WhoAmI());
type WhoAmIProviderProps = { children: React.ReactNode };
export const WhoAmIContextProvider = ({ children }: WhoAmIProviderProps) => {
const httpClient = useContext(HttpClientContext)!;
const keycloak = useContext(KeycloakContext);
const whoAmILoader = async () => {
if (keycloak === undefined) return undefined;
const realm = keycloak.realm();
return await httpClient
.doGet(`/admin/${realm}/console/whoami/`)
.then((r) => r.data as WhoAmIRepresentation);
};
return (
<DataLoader loader={whoAmILoader}>
{(whoamirep) => (
<WhoAmIContext.Provider
value={new WhoAmI(keycloak?.realm(), whoamirep)}
>
{children}
</WhoAmIContext.Provider>
)}
</DataLoader>
);
};

View file

@ -0,0 +1,28 @@
import whoamiMock from "./mock-whoami.json";
import { WhoAmI } from "../WhoAmI";
test("returns display name", () => {
const whoami = new WhoAmI("master", whoamiMock);
expect(whoami.getDisplayName()).toEqual("Stan Silvert");
});
test("returns correct home realm", () => {
let whoami = new WhoAmI("myrealm", whoamiMock);
expect(whoami.getHomeRealm()).toEqual("myrealm");
whoami = new WhoAmI(undefined, whoamiMock);
expect(whoami.getHomeRealm()).toEqual("master");
});
test("can not create realm", () => {
const whoami = new WhoAmI("master", whoamiMock);
expect(whoami.canCreateRealm()).toEqual(false);
});
test("getRealmAccess", () => {
const whoami = new WhoAmI("master", whoamiMock);
expect(Object.keys(whoami.getRealmAccess()).length).toEqual(2);
expect(whoami.getRealmAccess()["master"].length).toEqual(18);
});
//TODO: When we have easy access to i18n, create test for setting locale.
// Tested manually and it does work.

View file

@ -0,0 +1,49 @@
{
"userId": "1b635073-7ac8-49db-8eb9-f9fa9cd15bf5",
"realm": "master",
"displayName": "Stan Silvert",
"locale": "en",
"createRealm": false,
"realm_access": {
"aaa": [
"view-identity-providers",
"view-realm",
"manage-identity-providers",
"impersonation",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
],
"master": [
"view-realm",
"view-identity-providers",
"manage-identity-providers",
"impersonation",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
]
}
}

View file

@ -0,0 +1,8 @@
export default interface WhoAmIRepresentation {
userId: string;
realm: string;
displayName: string;
locale: string;
createRealm: boolean;
realm_access: { [key: string]: string[] };
}