use context for adminClient (#28693)

* use context for adminClient

Now we can reuse the components as we can use the adminClient from the context

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* split environment into base, admin and account

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added type to useEnvironment

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Erik Jan de Wit 2024-05-08 10:23:43 +02:00 committed by GitHub
parent dde2746595
commit e28aa90fcb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
218 changed files with 1110 additions and 756 deletions

View file

@ -12,11 +12,9 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { LinkIcon, UnlinkIcon } from "@patternfly/react-icons"; import { LinkIcon, UnlinkIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { IconMapper, useAlerts } from "@keycloak/keycloak-ui-shared"; import { IconMapper, useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { linkAccount, unLinkAccount } from "../api/methods"; import { linkAccount, unLinkAccount } from "../api/methods";
import { LinkedAccountRepresentation } from "../api/representations"; import { LinkedAccountRepresentation } from "../api/representations";
import { useEnvironment } from "../root/KeycloakContext";
type AccountRowProps = { type AccountRowProps = {
account: LinkedAccountRepresentation; account: LinkedAccountRepresentation;

View file

@ -23,7 +23,7 @@ import {
} from "@patternfly/react-icons"; } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ContinueCancelModal, useAlerts } from "@keycloak/keycloak-ui-shared"; import { ContinueCancelModal, useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { deleteSession, getDevices } from "../api/methods"; import { deleteSession, getDevices } from "../api/methods";
import { import {
ClientRepresentation, ClientRepresentation,
@ -32,7 +32,6 @@ import {
} from "../api/representations"; } from "../api/representations";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { useEnvironment } from "../root/KeycloakContext";
import { formatDate } from "../utils/formatDate"; import { formatDate } from "../utils/formatDate";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";

View file

@ -7,7 +7,7 @@ import { EmptyRow } from "../components/datalist/EmptyRow";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
import { AccountRow } from "./AccountRow"; import { AccountRow } from "./AccountRow";
import { useEnvironment } from "../root/KeycloakContext"; import { useEnvironment } from "@keycloak/keycloak-ui-shared";
export const LinkedAccounts = () => { export const LinkedAccounts = () => {
const { t } = useTranslation(); const { t } = useTranslation();

View file

@ -18,6 +18,7 @@ import {
import { EllipsisVIcon } from "@patternfly/react-icons"; import { EllipsisVIcon } from "@patternfly/react-icons";
import { CSSProperties, useState } from "react"; import { CSSProperties, useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { useEnvironment } from "@keycloak/keycloak-ui-shared";
import { getCredentials } from "../api/methods"; import { getCredentials } from "../api/methods";
import { import {
CredentialContainer, CredentialContainer,
@ -26,7 +27,6 @@ import {
import { EmptyRow } from "../components/datalist/EmptyRow"; import { EmptyRow } from "../components/datalist/EmptyRow";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { useEnvironment } from "../root/KeycloakContext";
import { formatDate } from "../utils/formatDate"; import { formatDate } from "../utils/formatDate";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";

View file

@ -1,9 +1,10 @@
import { KeycloakContext } from "@keycloak/keycloak-ui-shared";
import { BaseEnvironment } from "@keycloak/keycloak-ui-shared/dist/context/environment";
import { CallOptions } from "./api/methods"; import { CallOptions } from "./api/methods";
import { Links, parseLinks } from "./api/parse-links"; import { Links, parseLinks } from "./api/parse-links";
import { parseResponse } from "./api/parse-response"; import { parseResponse } from "./api/parse-response";
import { Permission, Resource, Scope } from "./api/representations"; import { Permission, Resource, Scope } from "./api/representations";
import { request } from "./api/request"; import { request } from "./api/request";
import { KeycloakContext } from "./root/KeycloakContext";
export const fetchResources = async ( export const fetchResources = async (
{ signal, context }: CallOptions, { signal, context }: CallOptions,
@ -43,7 +44,7 @@ export const fetchPermission = async (
}; };
export const updateRequest = ( export const updateRequest = (
context: KeycloakContext, context: KeycloakContext<BaseEnvironment>,
resourceId: string, resourceId: string,
username: string, username: string,
scopes: Scope[] | string[], scopes: Scope[] | string[],
@ -54,7 +55,7 @@ export const updateRequest = (
}); });
export const updatePermissions = ( export const updatePermissions = (
context: KeycloakContext, context: KeycloakContext<BaseEnvironment>,
resourceId: string, resourceId: string,
permissions: Permission[], permissions: Permission[],
) => ) =>

View file

@ -1,4 +1,8 @@
import { KeycloakContext } from "../root/KeycloakContext"; import {
AccountEnvironment,
KeycloakContext,
} from "@keycloak/keycloak-ui-shared";
import { BaseEnvironment } from "@keycloak/keycloak-ui-shared/dist/context/environment";
import { joinPath } from "../utils/joinPath"; import { joinPath } from "../utils/joinPath";
import { parseResponse } from "./parse-response"; import { parseResponse } from "./parse-response";
import { import {
@ -13,7 +17,7 @@ import {
import { request } from "./request"; import { request } from "./request";
export type CallOptions = { export type CallOptions = {
context: KeycloakContext; context: KeycloakContext<BaseEnvironment>;
signal?: AbortSignal; signal?: AbortSignal;
}; };
@ -41,7 +45,7 @@ export async function getSupportedLocales({
} }
export async function savePersonalInfo( export async function savePersonalInfo(
context: KeycloakContext, context: KeycloakContext<AccountEnvironment>,
info: UserRepresentation, info: UserRepresentation,
): Promise<void> { ): Promise<void> {
const response = await request("/", context, { body: info, method: "POST" }); const response = await request("/", context, { body: info, method: "POST" });
@ -81,11 +85,17 @@ export async function getApplications({
return parseResponse<ClientRepresentation[]>(response); return parseResponse<ClientRepresentation[]>(response);
} }
export async function deleteConsent(context: KeycloakContext, id: string) { export async function deleteConsent(
context: KeycloakContext<BaseEnvironment>,
id: string,
) {
return request(`/applications/${id}/consent`, context, { method: "DELETE" }); return request(`/applications/${id}/consent`, context, { method: "DELETE" });
} }
export async function deleteSession(context: KeycloakContext, id?: string) { export async function deleteSession(
context: KeycloakContext<BaseEnvironment>,
id?: string,
) {
return request(`/sessions${id ? `/${id}` : ""}`, context, { return request(`/sessions${id ? `/${id}` : ""}`, context, {
method: "DELETE", method: "DELETE",
}); });
@ -104,7 +114,7 @@ export async function getLinkedAccounts({ signal, context }: CallOptions) {
} }
export async function unLinkAccount( export async function unLinkAccount(
context: KeycloakContext, context: KeycloakContext<BaseEnvironment>,
account: LinkedAccountRepresentation, account: LinkedAccountRepresentation,
) { ) {
const response = await request( const response = await request(
@ -119,7 +129,7 @@ export async function unLinkAccount(
} }
export async function linkAccount( export async function linkAccount(
context: KeycloakContext, context: KeycloakContext<BaseEnvironment>,
account: LinkedAccountRepresentation, account: LinkedAccountRepresentation,
) { ) {
const redirectUri = encodeURIComponent( const redirectUri = encodeURIComponent(

View file

@ -1,8 +1,8 @@
import { Environment } from "../environment"; import { KeycloakContext } from "@keycloak/keycloak-ui-shared";
import { BaseEnvironment } from "@keycloak/keycloak-ui-shared/dist/context/environment";
import Keycloak from "keycloak-js"; import Keycloak from "keycloak-js";
import { CONTENT_TYPE_HEADER, CONTENT_TYPE_JSON } from "./constants";
import { joinPath } from "../utils/joinPath"; import { joinPath } from "../utils/joinPath";
import { KeycloakContext } from "../root/KeycloakContext"; import { CONTENT_TYPE_HEADER, CONTENT_TYPE_JSON } from "./constants";
export type RequestOptions = { export type RequestOptions = {
signal?: AbortSignal; signal?: AbortSignal;
@ -35,7 +35,7 @@ async function _request(
export async function request( export async function request(
path: string, path: string,
{ environment, keycloak }: KeycloakContext, { environment, keycloak }: KeycloakContext<BaseEnvironment>,
opts: RequestOptions = {}, opts: RequestOptions = {},
) { ) {
return _request(url(environment, path), { return _request(url(environment, path), {
@ -44,7 +44,7 @@ export async function request(
}); });
} }
export const url = (environment: Environment, path: string) => export const url = (environment: BaseEnvironment, path: string) =>
new URL( new URL(
joinPath(environment.authUrl, "realms", environment.realm, "account", path), joinPath(environment.authUrl, "realms", environment.realm, "account", path),
); );

View file

@ -22,12 +22,11 @@ import {
} from "@patternfly/react-icons"; } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ContinueCancelModal, useAlerts } from "@keycloak/keycloak-ui-shared"; import { ContinueCancelModal, useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { deleteConsent, getApplications } from "../api/methods"; import { deleteConsent, getApplications } from "../api/methods";
import { ClientRepresentation } from "../api/representations"; import { ClientRepresentation } from "../api/representations";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { useEnvironment } from "../root/KeycloakContext";
import { formatDate } from "../utils/formatDate"; import { formatDate } from "../utils/formatDate";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";

View file

@ -1,7 +1,7 @@
import { Spinner } from "@patternfly/react-core"; import { Spinner } from "@patternfly/react-core";
import { Suspense, lazy, useMemo, useState } from "react"; import { Suspense, lazy, useMemo, useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useEnvironment } from "../root/KeycloakContext"; import { useEnvironment } from "@keycloak/keycloak-ui-shared";
import { MenuItem } from "../root/PageNav"; import { MenuItem } from "../root/PageNav";
import { ContentComponentParams } from "../routes"; import { ContentComponentParams } from "../routes";
import { joinPath } from "../utils/joinPath"; import { joinPath } from "../utils/joinPath";

View file

@ -8,10 +8,10 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useEnvironment } from "@keycloak/keycloak-ui-shared";
import { getGroups } from "../api/methods"; import { getGroups } from "../api/methods";
import { Group } from "../api/representations"; import { Group } from "../api/representations";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { useEnvironment } from "../root/KeycloakContext";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
export const Groups = () => { export const Groups = () => {

View file

@ -1,8 +1,7 @@
import { LanguageDetectorModule, createInstance } from "i18next"; import { LanguageDetectorModule, createInstance } from "i18next";
import HttpBackend from "i18next-http-backend"; import HttpBackend from "i18next-http-backend";
import { initReactI18next } from "react-i18next"; import { initReactI18next } from "react-i18next";
import { environment } from "@keycloak/keycloak-ui-shared";
import { environment } from "./environment";
import { joinPath } from "./utils/joinPath"; import { joinPath } from "./utils/joinPath";
const DEFAULT_LOCALE = "en"; const DEFAULT_LOCALE = "en";

View file

@ -1,7 +1,6 @@
export { PersonalInfo } from "./personal-info/PersonalInfo"; export { PersonalInfo } from "./personal-info/PersonalInfo";
export { ErrorPage } from "./root/ErrorPage"; export { ErrorPage } from "./root/ErrorPage";
export { Header } from "./root/Header"; export { Header } from "./root/Header";
export { KeycloakProvider, useEnvironment } from "./root/KeycloakContext";
export { PageNav } from "./root/PageNav"; export { PageNav } from "./root/PageNav";
export { DeviceActivity } from "./account-security/DeviceActivity"; export { DeviceActivity } from "./account-security/DeviceActivity";
export { LinkedAccounts } from "./account-security/LinkedAccounts"; export { LinkedAccounts } from "./account-security/LinkedAccounts";

View file

@ -1,9 +1,11 @@
import { import {
AccountEnvironment,
UserProfileFields, UserProfileFields,
beerify, beerify,
debeerify, debeerify,
setUserProfileServerError, setUserProfileServerError,
useAlerts, useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { import {
ActionGroup, ActionGroup,
@ -18,7 +20,6 @@ import { TFunction } from "i18next";
import { useState } from "react"; import { useState } from "react";
import { ErrorOption, useForm } from "react-hook-form"; import { ErrorOption, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import {
getPersonalInfo, getPersonalInfo,
getSupportedLocales, getSupportedLocales,
@ -29,14 +30,12 @@ import {
UserRepresentation, UserRepresentation,
} from "../api/representations"; } from "../api/representations";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { environment } from "../environment";
import { TFuncKey, i18n } from "../i18n"; import { TFuncKey, i18n } from "../i18n";
import { useEnvironment } from "../root/KeycloakContext";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
export const PersonalInfo = () => { export const PersonalInfo = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment<AccountEnvironment>();
const [userProfileMetadata, setUserProfileMetadata] = const [userProfileMetadata, setUserProfileMetadata] =
useState<UserProfileMetadata>(); useState<UserProfileMetadata>();
const [supportedLocales, setSupportedLocales] = useState<string[]>([]); const [supportedLocales, setSupportedLocales] = useState<string[]>([]);
@ -106,7 +105,7 @@ export const PersonalInfo = () => {
form={form} form={form}
userProfileMetadata={userProfileMetadata} userProfileMetadata={userProfileMetadata}
supportedLocales={supportedLocales} supportedLocales={supportedLocales}
currentLocale={environment.locale} currentLocale={context.environment.locale}
t={ t={
((key: unknown, params) => ((key: unknown, params) =>
t(key as TFuncKey, params as any)) as TFunction t(key as TFuncKey, params as any)) as TFunction

View file

@ -2,15 +2,14 @@ import { Button, Form, Modal } from "@patternfly/react-core";
import { Fragment, useEffect } from "react"; import { Fragment, useEffect } from "react";
import { FormProvider, useFieldArray, useForm } from "react-hook-form"; import { FormProvider, useFieldArray, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import {
SelectControl, SelectControl,
TextControl, TextControl,
useAlerts, useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { updatePermissions } from "../api"; import { updatePermissions } from "../api";
import type { Permission, Resource } from "../api/representations"; import type { Permission, Resource } from "../api/representations";
import { useEnvironment } from "../root/KeycloakContext";
type EditTheResourceProps = { type EditTheResourceProps = {
resource: Resource; resource: Resource;

View file

@ -11,11 +11,9 @@ import { UserCheckIcon } from "@patternfly/react-icons";
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table"; import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAlerts } from "@keycloak/keycloak-ui-shared"; import { useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { fetchPermission, updateRequest } from "../api"; import { fetchPermission, updateRequest } from "../api";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useEnvironment } from "../root/KeycloakContext";
type PermissionRequestProps = { type PermissionRequestProps = {
resource: Resource; resource: Resource;

View file

@ -32,13 +32,11 @@ import {
} from "@patternfly/react-table"; } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ContinueCancelModal, useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { ContinueCancelModal, useAlerts } from "@keycloak/keycloak-ui-shared";
import { fetchPermission, fetchResources, updatePermissions } from "../api"; import { fetchPermission, fetchResources, updatePermissions } from "../api";
import { getPermissionRequests } from "../api/methods"; import { getPermissionRequests } from "../api/methods";
import { Links } from "../api/parse-links"; import { Links } from "../api/parse-links";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useEnvironment } from "../root/KeycloakContext";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
import { EditTheResource } from "./EditTheResource"; import { EditTheResource } from "./EditTheResource";
import { PermissionRequest } from "./PermissionRequest"; import { PermissionRequest } from "./PermissionRequest";

View file

@ -22,10 +22,10 @@ import {
FormErrorText, FormErrorText,
SelectControl, SelectControl,
useAlerts, useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { updateRequest } from "../api"; import { updateRequest } from "../api";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useEnvironment } from "../root/KeycloakContext";
import { SharedWith } from "./SharedWith"; import { SharedWith } from "./SharedWith";
type ShareTheResourceProps = { type ShareTheResourceProps = {

View file

@ -2,11 +2,13 @@ import { Button } from "@patternfly/react-core";
import { ExternalLinkSquareAltIcon } from "@patternfly/react-icons"; import { ExternalLinkSquareAltIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useHref } from "react-router-dom"; import { useHref } from "react-router-dom";
import { KeycloakMasthead, label } from "@keycloak/keycloak-ui-shared"; import {
KeycloakMasthead,
import { environment } from "../environment"; environment,
label,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { joinPath } from "../utils/joinPath"; import { joinPath } from "../utils/joinPath";
import { useEnvironment } from "./KeycloakContext";
import style from "./header.module.css"; import style from "./header.module.css";

View file

@ -1,93 +0,0 @@
import { Spinner } from "@patternfly/react-core";
import Keycloak from "keycloak-js";
import {
PropsWithChildren,
createContext,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { AlertProvider, Help } from "@keycloak/keycloak-ui-shared";
import { Environment } from "../environment";
import { ErrorPage } from "./ErrorPage";
export type KeycloakContext = KeycloakContextProps & {
keycloak: Keycloak;
};
const KeycloakEnvContext = createContext<KeycloakContext | undefined>(
undefined,
);
export const useEnvironment = () => {
const context = useContext(KeycloakEnvContext);
if (!context)
throw Error(
"no environment provider in the hierarchy make sure to add the provider",
);
return context;
};
type KeycloakContextProps = {
environment: Environment;
};
export const KeycloakProvider = ({
environment,
children,
}: PropsWithChildren<KeycloakContextProps>) => {
const calledOnce = useRef(false);
const [init, setInit] = useState(false);
const [error, setError] = useState<unknown>();
const keycloak = useMemo(
() => {
const keycloak = new Keycloak({
url: environment.authUrl,
realm: environment.realm,
clientId: environment.clientId,
});
keycloak.onAuthLogout = () => keycloak.login();
return keycloak;
},
[environment],
);
useEffect(() => {
// only needed in dev mode
if (calledOnce.current) {
return;
}
const init = () => keycloak.init({
onLoad: "check-sso",
pkceMethod: "S256",
responseMode: "query",
});
init()
.then(() => setInit(true))
.catch((error) => setError(error));
calledOnce.current = true;
}, [keycloak]);
if (error) {
return <ErrorPage error={error} />;
}
if (!init) {
return <Spinner />;
}
return (
<KeycloakEnvContext.Provider value={{ environment, keycloak }}>
<AlertProvider>
<Help>{children}</Help>
</AlertProvider>
</KeycloakEnvContext.Provider>
);
};

View file

@ -4,8 +4,8 @@ import {
NavItem, NavItem,
NavList, NavList,
PageSidebar, PageSidebar,
Spinner,
PageSidebarBody, PageSidebarBody,
Spinner,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { import {
PropsWithChildren, PropsWithChildren,
@ -22,11 +22,15 @@ import {
useLinkClickHandler, useLinkClickHandler,
useLocation, useLocation,
} from "react-router-dom"; } from "react-router-dom";
import {
AccountEnvironment,
environment,
useEnvironment,
type Feature,
} from "@keycloak/keycloak-ui-shared";
import fetchContentJson from "../content/fetchContent"; import fetchContentJson from "../content/fetchContent";
import { environment, type Feature } from "../environment";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
import { useEnvironment } from "./KeycloakContext";
type RootMenuItem = { type RootMenuItem = {
label: TFuncKey; label: TFuncKey;
@ -45,7 +49,7 @@ export type MenuItem = RootMenuItem | MenuItemWithChildren;
export const PageNav = () => { export const PageNav = () => {
const [menuItems, setMenuItems] = useState<MenuItem[]>(); const [menuItems, setMenuItems] = useState<MenuItem[]>();
const context = useEnvironment(); const context = useEnvironment<AccountEnvironment>();
usePromise((signal) => fetchContentJson({ signal, context }), setMenuItems); usePromise((signal) => fetchContentJson({ signal, context }), setMenuItems);
return ( return (
@ -82,7 +86,7 @@ function NavMenuItem({ menuItem }: NavMenuItemProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
environment: { features }, environment: { features },
} = useEnvironment(); } = useEnvironment<AccountEnvironment>();
const { pathname } = useLocation(); const { pathname } = useLocation();
const isActive = useMemo( const isActive = useMemo(
() => matchMenuItem(pathname, menuItem), () => matchMenuItem(pathname, menuItem),

View file

@ -1,9 +1,8 @@
import { KeycloakProvider, environment } from "@keycloak/keycloak-ui-shared";
import { Page, Spinner } from "@patternfly/react-core"; import { Page, Spinner } from "@patternfly/react-core";
import { Suspense } from "react"; import { Suspense } from "react";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import { environment } from "../environment";
import { Header } from "./Header"; import { Header } from "./Header";
import { KeycloakProvider } from "./KeycloakContext";
import { PageNav } from "./PageNav"; import { PageNav } from "./PageNav";
export const Root = () => { export const Root = () => {

View file

@ -1,9 +1,8 @@
import { lazy } from "react"; import { lazy } from "react";
import type { IndexRouteObject, RouteObject } from "react-router-dom"; import type { IndexRouteObject, RouteObject } from "react-router-dom";
import { environment } from "@keycloak/keycloak-ui-shared";
import { ErrorPage } from "./root/ErrorPage"; import { ErrorPage } from "./root/ErrorPage";
import { Root } from "./root/Root"; import { Root } from "./root/Root";
import { environment } from "./environment";
const DeviceActivity = lazy(() => import("./account-security/DeviceActivity")); const DeviceActivity = lazy(() => import("./account-security/DeviceActivity"));
const LinkedAccounts = lazy(() => import("./account-security/LinkedAccounts")); const LinkedAccounts = lazy(() => import("./account-security/LinkedAccounts"));

View file

@ -124,7 +124,7 @@
<![CDATA[ <![CDATA[
<script id="environment" type="application/json"> <script id="environment" type="application/json">
{ {
"loginRealm": "${loginRealm!"master"}", "realm": "${loginRealm!"master"}",
"clientId": "${clientId}", "clientId": "${clientId}",
"authServerUrl": "${authServerUrl}", "authServerUrl": "${authServerUrl}",
"authUrl": "${authUrl}", "authUrl": "${authUrl}",

View file

@ -1,10 +1,14 @@
import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import { Page } from "@patternfly/react-core"; import { Page } from "@patternfly/react-core";
import { PropsWithChildren, Suspense } from "react"; import { PropsWithChildren, Suspense, useEffect, useState } from "react";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import { Help, mainPageContentId } from "@keycloak/keycloak-ui-shared"; import {
mainPageContentId,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { Header } from "./PageHeader"; import { Header } from "./PageHeader";
import { PageNav } from "./PageNav"; import { PageNav } from "./PageNav";
import { AdminClientContext, initAdminClient } from "./admin-client";
import { AlertProvider } from "./components/alert/Alerts"; import { AlertProvider } from "./components/alert/Alerts";
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs"; import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
import { ErrorRenderer } from "./components/error/ErrorRenderer"; import { ErrorRenderer } from "./components/error/ErrorRenderer";
@ -30,11 +34,9 @@ const AppContexts = ({ children }: PropsWithChildren) => (
<RealmsProvider> <RealmsProvider>
<RecentRealmsProvider> <RecentRealmsProvider>
<AccessContextProvider> <AccessContextProvider>
<Help> <AlertProvider>
<AlertProvider> <SubGroups>{children}</SubGroups>
<SubGroups>{children}</SubGroups> </AlertProvider>
</AlertProvider>
</Help>
</AccessContextProvider> </AccessContextProvider>
</RecentRealmsProvider> </RecentRealmsProvider>
</RealmsProvider> </RealmsProvider>
@ -45,23 +47,37 @@ const AppContexts = ({ children }: PropsWithChildren) => (
); );
export const App = () => { export const App = () => {
const { keycloak, environment } = useEnvironment();
const [adminClient, setAdminClient] = useState<KeycloakAdminClient>();
useEffect(() => {
const init = async () => {
const client = await initAdminClient(keycloak, environment);
setAdminClient(client);
};
init().catch(console.error);
}, []);
if (!adminClient) return <KeycloakSpinner />;
return ( return (
<AppContexts> <AdminClientContext.Provider value={{ keycloak, adminClient }}>
<Page <AppContexts>
header={<Header />} <Page
isManagedSidebar header={<Header />}
sidebar={<PageNav />} isManagedSidebar
breadcrumb={<PageBreadCrumbs />} sidebar={<PageNav />}
mainContainerId={mainPageContentId} breadcrumb={<PageBreadCrumbs />}
> mainContainerId={mainPageContentId}
<ErrorBoundaryFallback fallback={ErrorRenderer}> >
<Suspense fallback={<KeycloakSpinner />}> <ErrorBoundaryFallback fallback={ErrorRenderer}>
<AuthWall> <Suspense fallback={<KeycloakSpinner />}>
<Outlet /> <AuthWall>
</AuthWall> <Outlet />
</Suspense> </AuthWall>
</ErrorBoundaryFallback> </Suspense>
</Page> </ErrorBoundaryFallback>
</AppContexts> </Page>
</AppContexts>
</AdminClientContext.Provider>
); );
}; };

View file

@ -18,16 +18,15 @@ import { BarsIcon, EllipsisVIcon, HelpIcon } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useHref } from "react-router-dom"; import { Link, useHref } from "react-router-dom";
import { useHelp } from "@keycloak/keycloak-ui-shared"; import { useEnvironment, useHelp } from "@keycloak/keycloak-ui-shared";
import { HelpHeader } from "./components/help-enabler/HelpHeader"; import { HelpHeader } from "./components/help-enabler/HelpHeader";
import { useRealm } from "./context/realm-context/RealmContext"; import { useRealm } from "./context/realm-context/RealmContext";
import { useWhoAmI } from "./context/whoami/WhoAmI"; import { useWhoAmI } from "./context/whoami/WhoAmI";
import { toDashboard } from "./dashboard/routes/Dashboard"; import { toDashboard } from "./dashboard/routes/Dashboard";
import environment from "./environment";
import { keycloak } from "./keycloak";
const ManageAccountDropdownItem = () => { const ManageAccountDropdownItem = () => {
const { keycloak } = useEnvironment();
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<DropdownItem <DropdownItem
@ -41,6 +40,7 @@ const ManageAccountDropdownItem = () => {
}; };
const SignOutDropdownItem = () => { const SignOutDropdownItem = () => {
const { keycloak } = useEnvironment();
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<DropdownItem <DropdownItem
@ -146,6 +146,7 @@ const UserDropdown = () => {
}; };
export const Header = () => { export const Header = () => {
const { environment, keycloak } = useEnvironment();
const { t } = useTranslation(); const { t } = useTranslation();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -0,0 +1,8 @@
import { KeycloakProvider, environment } from "@keycloak/keycloak-ui-shared";
import { App } from "./App";
export const Root = () => (
<KeycloakProvider environment={environment}>
<App />
</KeycloakProvider>
);

View file

@ -1,20 +1,41 @@
import KeycloakAdminClient from "@keycloak/keycloak-admin-client"; import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import {
createNamedContext,
useRequiredContext,
} from "@keycloak/keycloak-ui-shared";
import { BaseEnvironment } from "@keycloak/keycloak-ui-shared/dist/context/environment";
import type Keycloak from "keycloak-js";
import environment from "./environment"; export type AdminClientProps = {
import { keycloak } from "./keycloak"; keycloak: Keycloak;
adminClient: KeycloakAdminClient;
};
export const adminClient = new KeycloakAdminClient(); export const AdminClientContext = createNamedContext<
AdminClientProps | undefined
>("AdminClientContext", undefined);
adminClient.setConfig({ realmName: environment.loginRealm }); export const useAdminClient = () => useRequiredContext(AdminClientContext);
adminClient.baseUrl = environment.authUrl;
adminClient.registerTokenProvider({
async getAccessToken() {
try {
await keycloak.updateToken(5);
} catch (error) {
keycloak.login();
}
return keycloak.token; export async function initAdminClient(
}, keycloak: Keycloak,
}); environment: BaseEnvironment,
) {
const adminClient = new KeycloakAdminClient();
adminClient.setConfig({ realmName: environment.realm });
adminClient.baseUrl = environment.authUrl;
adminClient.registerTokenProvider({
async getAccessToken() {
try {
await keycloak.updateToken(5);
} catch (error) {
keycloak.login();
}
return keycloak.token;
},
});
return adminClient;
}

View file

@ -15,8 +15,6 @@ import { sortBy } from "lodash-es";
import { useState } from "react"; import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
@ -42,6 +40,7 @@ import { Policies } from "./policies/Policies";
import { AuthenticationTab, toAuthentication } from "./routes/Authentication"; import { AuthenticationTab, toAuthentication } from "./routes/Authentication";
import { toCreateFlow } from "./routes/CreateFlow"; import { toCreateFlow } from "./routes/CreateFlow";
import { toFlow } from "./routes/Flow"; import { toFlow } from "./routes/Flow";
import { useAdminClient } from "../admin-client";
type UsedBy = "SPECIFIC_CLIENTS" | "SPECIFIC_PROVIDERS" | "DEFAULT"; type UsedBy = "SPECIFIC_CLIENTS" | "SPECIFIC_PROVIDERS" | "DEFAULT";
@ -83,6 +82,7 @@ const AliasRenderer = ({ id, alias, usedBy, builtIn }: AuthenticationType) => {
}; };
export default function AuthenticationSection() { export default function AuthenticationSection() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { realm: realmName } = useRealm(); const { realm: realmName } = useRealm();
const [key, setKey] = useState(0); const [key, setKey] = useState(0);

View file

@ -10,11 +10,10 @@ import { SelectVariant } from "@patternfly/react-core/deprecated";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { REALM_FLOWS } from "./AuthenticationSection"; import { REALM_FLOWS } from "./AuthenticationSection";
import { useAdminClient } from "../admin-client";
type BindingForm = { type BindingForm = {
bindingType: keyof RealmRepresentation; bindingType: keyof RealmRepresentation;
@ -26,6 +25,8 @@ type BindFlowDialogProps = {
}; };
export const BindFlowDialog = ({ flowAlias, onClose }: BindFlowDialogProps) => { export const BindFlowDialog = ({ flowAlias, onClose }: BindFlowDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<BindingForm>(); const form = useForm<BindingForm>();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -11,8 +11,7 @@ import { useEffect } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { NameDescription } from "./form/NameDescription"; import { NameDescription } from "./form/NameDescription";
@ -31,6 +30,8 @@ export const DuplicateFlowModal = ({
toggleDialog, toggleDialog,
onComplete, onComplete,
}: DuplicateFlowModalProps) => { }: DuplicateFlowModalProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<AuthenticationFlowRepresentation>({ mode: "onChange" }); const form = useForm<AuthenticationFlowRepresentation>({ mode: "onChange" });
const { setValue, getValues, handleSubmit } = form; const { setValue, getValues, handleSubmit } = form;

View file

@ -9,9 +9,8 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useEffect } from "react"; import { useEffect } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { adminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { NameDescription } from "./form/NameDescription"; import { NameDescription } from "./form/NameDescription";
@ -21,6 +20,8 @@ type EditFlowModalProps = {
}; };
export const EditFlowModal = ({ flow, toggleDialog }: EditFlowModalProps) => { export const EditFlowModal = ({ flow, toggleDialog }: EditFlowModalProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const form = useForm<AuthenticationFlowRepresentation>({ mode: "onChange" }); const form = useForm<AuthenticationFlowRepresentation>({ mode: "onChange" });

View file

@ -21,7 +21,7 @@ import { DomainIcon, TableIcon } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { adminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ViewHeader } from "../components/view-header/ViewHeader"; import { ViewHeader } from "../components/view-header/ViewHeader";
@ -52,6 +52,8 @@ export const providerConditionFilter = (
) => value.displayName?.startsWith("Condition "); ) => value.displayName?.startsWith("Condition ");
export default function FlowDetails() { export default function FlowDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { realm } = useRealm(); const { realm } = useRealm();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -3,8 +3,7 @@ import type RequiredActionProviderSimpleRepresentation from "@keycloak/keycloak-
import { AlertVariant, Switch } from "@patternfly/react-core"; import { AlertVariant, Switch } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { toKey } from "../util"; import { toKey } from "../util";
@ -22,6 +21,8 @@ type Row = {
}; };
export const RequiredActions = () => { export const RequiredActions = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -8,8 +8,7 @@ import {
import { PlusIcon } from "@patternfly/react-icons"; import { PlusIcon } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import type { ExpandableExecution } from "../execution-model"; import type { ExpandableExecution } from "../execution-model";
import { AddStepModal, FlowType } from "./modals/AddStepModal"; import { AddStepModal, FlowType } from "./modals/AddStepModal";
@ -29,6 +28,8 @@ export const AddFlowDropdown = ({
onAddExecution, onAddExecution,
onAddFlow, onAddFlow,
}: AddFlowDropdownProps) => { }: AddFlowDropdownProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);

View file

@ -15,7 +15,7 @@ import { useEffect, useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
@ -34,6 +34,8 @@ type ExecutionConfigModalProps = {
export const ExecutionConfigModal = ({ export const ExecutionConfigModal = ({
execution, execution,
}: ExecutionConfigModalProps) => { }: ExecutionConfigModalProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -10,7 +10,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { CheckCircleIcon } from "@patternfly/react-icons"; import { CheckCircleIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { fetchUsedBy } from "../../components/role-mapping/resource"; import { fetchUsedBy } from "../../components/role-mapping/resource";
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
import useToggle from "../../utils/useToggle"; import useToggle from "../../utils/useToggle";
@ -36,6 +36,8 @@ type UsedByModalProps = {
}; };
const UsedByModal = ({ id, isSpecificClient, onClose }: UsedByModalProps) => { const UsedByModal = ({ id, isSpecificClient, onClose }: UsedByModalProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const loader = async ( const loader = async (
@ -43,7 +45,7 @@ const UsedByModal = ({ id, isSpecificClient, onClose }: UsedByModalProps) => {
max?: number, max?: number,
search?: string, search?: string,
): Promise<{ name: string }[]> => { ): Promise<{ name: string }[]> => {
const result = await fetchUsedBy({ const result = await fetchUsedBy(adminClient, {
id, id,
type: isSpecificClient ? "clients" : "idp", type: isSpecificClient ? "clients" : "idp",
first: first || 0, first: first || 0,

View file

@ -10,12 +10,11 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { adminClient } from "../../../admin-client";
import { PaginatingTableToolbar } from "../../../components/table-toolbar/PaginatingTableToolbar"; import { PaginatingTableToolbar } from "../../../components/table-toolbar/PaginatingTableToolbar";
import { useFetch } from "../../../utils/useFetch"; import { useFetch } from "../../../utils/useFetch";
import useLocaleSort, { mapByKey } from "../../../utils/useLocaleSort"; import useLocaleSort, { mapByKey } from "../../../utils/useLocaleSort";
import { providerConditionFilter } from "../../FlowDetails"; import { providerConditionFilter } from "../../FlowDetails";
import { useAdminClient } from "../../../admin-client";
type AuthenticationProviderListProps = { type AuthenticationProviderListProps = {
list?: AuthenticationProviderRepresentation[]; list?: AuthenticationProviderRepresentation[];
@ -56,6 +55,8 @@ type AddStepModalProps = {
}; };
export const AddStepModal = ({ name, type, onSelect }: AddStepModalProps) => { export const AddStepModal = ({ name, type, onSelect }: AddStepModalProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [value, setValue] = useState<AuthenticationProviderRepresentation>(); const [value, setValue] = useState<AuthenticationProviderRepresentation>();

View file

@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../../admin-client"; import { useAdminClient } from "../../../admin-client";
import { useFetch } from "../../../utils/useFetch"; import { useFetch } from "../../../utils/useFetch";
type AddSubFlowProps = { type AddSubFlowProps = {
@ -33,6 +33,8 @@ export const AddSubFlowModal = ({
onConfirm, onConfirm,
onCancel, onCancel,
}: AddSubFlowProps) => { }: AddSubFlowProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<Flow>(); const form = useForm<Flow>();
const [formProviders, setFormProviders] = const [formProviders, setFormProviders] =

View file

@ -8,9 +8,8 @@ import {
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { SelectControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
@ -22,6 +21,8 @@ import { NameDescription } from "./NameDescription";
const TYPES = ["basic-flow", "client-flow"] as const; const TYPES = ["basic-flow", "client-flow"] as const;
export default function CreateFlow() { export default function CreateFlow() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -10,7 +10,7 @@ import { useEffect } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
@ -33,6 +33,8 @@ type FormFields = Omit<
>; >;
export const CibaPolicy = ({ realm, realmUpdated }: CibaPolicyProps) => { export const CibaPolicy = ({ realm, realmUpdated }: CibaPolicyProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<FormFields>({ mode: "onChange" }); const form = useForm<FormFields>({ mode: "onChange" });
const { realm: realmName } = useRealm(); const { realm: realmName } = useRealm();

View file

@ -19,7 +19,7 @@ import {
SelectControl, SelectControl,
SwitchControl, SwitchControl,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl"; import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl";
@ -43,6 +43,8 @@ type FormFields = Omit<
>; >;
export const OtpPolicy = ({ realm, realmUpdated }: OtpPolicyProps) => { export const OtpPolicy = ({ realm, realmUpdated }: OtpPolicyProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<FormFields>({ mode: "onChange", defaultValues: realm }); const form = useForm<FormFields>({ mode: "onChange", defaultValues: realm });
const { const {

View file

@ -7,15 +7,15 @@ import {
ButtonVariant, ButtonVariant,
Divider, Divider,
EmptyState, EmptyState,
EmptyStateActions,
EmptyStateBody, EmptyStateBody,
EmptyStateFooter,
EmptyStateHeader,
EmptyStateIcon, EmptyStateIcon,
PageSection, PageSection,
Toolbar, Toolbar,
ToolbarContent, ToolbarContent,
ToolbarItem, ToolbarItem,
EmptyStateActions,
EmptyStateHeader,
EmptyStateFooter,
Select, Select,
SelectOption, SelectOption,
MenuToggle, MenuToggle,
@ -25,8 +25,7 @@ import { PlusCircleIcon } from "@patternfly/react-icons";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
@ -94,6 +93,8 @@ export const PasswordPolicy = ({
realm, realm,
realmUpdated, realmUpdated,
}: PasswordPolicyProps) => { }: PasswordPolicyProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { passwordPolicies } = useServerInfo(); const { passwordPolicies } = useServerInfo();

View file

@ -2,8 +2,7 @@ import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/r
import { Tab, Tabs, TabTitleText } from "@patternfly/react-core"; import { Tab, Tabs, TabTitleText } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
@ -13,6 +12,8 @@ import { PasswordPolicy } from "./PasswordPolicy";
import { WebauthnPolicy } from "./WebauthnPolicy"; import { WebauthnPolicy } from "./WebauthnPolicy";
export const Policies = () => { export const Policies = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [subTab, setSubTab] = useState(1); const [subTab, setSubTab] = useState(1);
const { realm: realmName } = useRealm(); const { realm: realmName } = useRealm();

View file

@ -22,7 +22,6 @@ import {
TextControl, TextControl,
useHelp, useHelp,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
@ -30,6 +29,7 @@ import { TimeSelectorControl } from "../../components/time-selector/TimeSelector
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
import { useAdminClient } from "../../admin-client";
import "./webauthn-policy.css"; import "./webauthn-policy.css";
const SIGNATURE_ALGORITHMS = [ const SIGNATURE_ALGORITHMS = [
@ -108,6 +108,8 @@ export const WebauthnPolicy = ({
realmUpdated, realmUpdated,
isPasswordLess = false, isPasswordLess = false,
}: WebauthnPolicyProps) => { }: WebauthnPolicyProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm: realmName } = useRealm(); const { realm: realmName } = useRealm();

View file

@ -2,7 +2,7 @@ import { AlertVariant } from "@patternfly/react-core";
import { Select } from "@patternfly/react-core/deprecated"; import { Select } from "@patternfly/react-core/deprecated";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client";
import type { Row } from "../clients/scopes/ClientScopes"; import type { Row } from "../clients/scopes/ClientScopes";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { import {
@ -24,6 +24,8 @@ export const ChangeTypeDropdown = ({
selectedRows, selectedRows,
refresh, refresh,
}: ChangeTypeDropdownProps) => { }: ChangeTypeDropdownProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -44,12 +46,13 @@ export const ChangeTypeDropdown = ({
selectedRows.map((row) => { selectedRows.map((row) => {
return clientId return clientId
? changeClientScope( ? changeClientScope(
adminClient,
clientId, clientId,
row, row,
row.type, row.type,
value as ClientScope, value as ClientScope,
) )
: changeScope(row, value as ClientScope); : changeScope(adminClient, row, value as ClientScope);
}), }),
); );
setOpen(false); setOpen(false);

View file

@ -14,8 +14,7 @@ import { cellWidth } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import type { Row } from "../clients/scopes/ClientScopes"; import type { Row } from "../clients/scopes/ClientScopes";
import { getProtocolName } from "../clients/utils"; import { getProtocolName } from "../clients/utils";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
@ -56,6 +55,8 @@ type TypeSelectorProps = ClientScopeDefaultOptionalType & {
}; };
const TypeSelector = (scope: TypeSelectorProps) => { const TypeSelector = (scope: TypeSelectorProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
@ -66,7 +67,7 @@ const TypeSelector = (scope: TypeSelectorProps) => {
all all
onSelect={async (value) => { onSelect={async (value) => {
try { try {
await changeScope(scope, value as AllClientScopeType); await changeScope(adminClient, scope, value as AllClientScopeType);
addAlert(t("clientScopeSuccess"), AlertVariant.success); addAlert(t("clientScopeSuccess"), AlertVariant.success);
scope.refresh(); scope.refresh();
} catch (error) { } catch (error) {
@ -90,6 +91,8 @@ const ClientScopeDetailLink = ({
}; };
export default function ClientScopesSection() { export default function ClientScopesSection() {
const { adminClient } = useAdminClient();
const { realm } = useRealm(); const { realm } = useRealm();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
@ -165,7 +168,7 @@ export default function ClientScopesSection() {
try { try {
for (const scope of selectedScopes) { for (const scope of selectedScopes) {
try { try {
await removeScope(scope); await removeScope(adminClient, scope);
} catch (error: any) { } catch (error: any) {
console.warn( console.warn(
"could not remove scope", "could not remove scope",

View file

@ -1,8 +1,7 @@
import { AlertVariant, PageSection } from "@patternfly/react-core"; import { AlertVariant, PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { import {
ClientScopeDefaultOptionalType, ClientScopeDefaultOptionalType,
@ -15,6 +14,8 @@ import { ScopeForm } from "./details/ScopeForm";
import { toClientScope } from "./routes/ClientScope"; import { toClientScope } from "./routes/ClientScope";
export default function CreateClientScope() { export default function CreateClientScope() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();
@ -37,7 +38,11 @@ export default function CreateClientScope() {
throw new Error(t("notFound")); throw new Error(t("notFound"));
} }
await changeScope({ ...clientScope, id: scope.id }, clientScope.type); await changeScope(
adminClient,
{ ...clientScope, id: scope.id },
clientScope.type,
);
addAlert(t("createClientScopeSuccess", AlertVariant.success)); addAlert(t("createClientScopeSuccess", AlertVariant.success));

View file

@ -15,8 +15,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useHelp } from "@keycloak/keycloak-ui-shared"; import { useHelp } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { import {
AllClientScopes, AllClientScopes,
@ -43,10 +42,12 @@ import {
ClientScopeTab, ClientScopeTab,
toClientScope, toClientScope,
} from "./routes/ClientScope"; } from "./routes/ClientScope";
import { toMapper } from "./routes/Mapper";
import { toClientScopes } from "./routes/ClientScopes"; import { toClientScopes } from "./routes/ClientScopes";
import { toMapper } from "./routes/Mapper";
export default function EditClientScope() { export default function EditClientScope() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();
@ -118,7 +119,7 @@ export default function EditClientScope() {
try { try {
await adminClient.clientScopes.update({ id }, clientScope); await adminClient.clientScopes.update({ id }, clientScope);
await changeScope({ ...clientScope, id }, clientScope.type); await changeScope(adminClient, { ...clientScope, id }, clientScope.type);
addAlert(t("updateSuccessClientScope"), AlertVariant.success); addAlert(t("updateSuccessClientScope"), AlertVariant.success);
} catch (error) { } catch (error) {

View file

@ -15,7 +15,8 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useMatch, useNavigate } from "react-router-dom"; import { Link, useMatch, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { toDedicatedScope } from "../../clients/routes/DedicatedScopeDetails";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
@ -28,9 +29,10 @@ import { useFetch } from "../../utils/useFetch";
import { useParams } from "../../utils/useParams"; import { useParams } from "../../utils/useParams";
import { toClientScope } from "../routes/ClientScope"; import { toClientScope } from "../routes/ClientScope";
import { MapperParams, MapperRoute } from "../routes/Mapper"; import { MapperParams, MapperRoute } from "../routes/Mapper";
import { toDedicatedScope } from "../../clients/routes/DedicatedScopeDetails";
export default function MappingDetails() { export default function MappingDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -16,8 +16,7 @@ import { useMemo, useState } from "react";
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form"; import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { import {
ConfirmDialogModal, ConfirmDialogModal,
@ -188,6 +187,8 @@ export type FormFields = Omit<
>; >;
export default function ClientDetails() { export default function ClientDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -2,7 +2,7 @@ import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/
import type UserSessionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userSessionRepresentation"; import type UserSessionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userSessionRepresentation";
import { PageSection } from "@patternfly/react-core"; import { PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { adminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import type { LoaderFunction } from "../components/table-toolbar/KeycloakDataTable"; import type { LoaderFunction } from "../components/table-toolbar/KeycloakDataTable";
import SessionsTable from "../sessions/SessionsTable"; import SessionsTable from "../sessions/SessionsTable";
@ -11,6 +11,8 @@ type ClientSessionsProps = {
}; };
export const ClientSessions = ({ client }: ClientSessionsProps) => { export const ClientSessions = ({ client }: ClientSessionsProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const loader: LoaderFunction<UserSessionRepresentation> = async ( const loader: LoaderFunction<UserSessionRepresentation> = async (

View file

@ -14,8 +14,7 @@ import { IRowData, TableText, cellWidth } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { adminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { FormattedLink } from "../components/external-link/FormattedLink"; import { FormattedLink } from "../components/external-link/FormattedLink";
@ -74,6 +73,7 @@ const ClientDescription = (client: ClientRepresentation) => (
); );
const ClientHomeLink = (client: ClientRepresentation) => { const ClientHomeLink = (client: ClientRepresentation) => {
const { adminClient } = useAdminClient();
const href = convertClientToUrl(client, adminClient.baseUrl); const href = convertClientToUrl(client, adminClient.baseUrl);
if (!href) { if (!href) {
@ -117,6 +117,8 @@ const ToolbarItems = () => {
}; };
export default function ClientsSection() { export default function ClientsSection() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -8,8 +8,7 @@ import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
@ -23,6 +22,8 @@ import { GeneralSettings } from "./GeneralSettings";
import { LoginSettings } from "./LoginSettings"; import { LoginSettings } from "./LoginSettings";
export default function NewClientForm() { export default function NewClientForm() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { realm } = useRealm(); const { realm } = useRealm();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -8,7 +8,7 @@ import {
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
type FormFields = { type FormFields = {
@ -28,6 +28,8 @@ export const AddHostDialog = ({
onAdded, onAdded,
onClose, onClose,
}: AddHostDialogProps) => { }: AddHostDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<FormFields>(); const form = useForm<FormFields>();
const { const {

View file

@ -8,21 +8,20 @@ import {
import { useState } from "react"; import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormAccess } from "../../components/form/FormAccess";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { adminClient } from "../../admin-client"; import { FormAccess } from "../../components/form/FormAccess";
import { KeyValueInput } from "../../components/key-value-form/KeyValueInput"; import { KeyValueInput } from "../../components/key-value-form/KeyValueInput";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { TimeSelector } from "../../components/time-selector/TimeSelector"; import { TimeSelector } from "../../components/time-selector/TimeSelector";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { convertAttributeNameToForm } from "../../util"; import { convertAttributeNameToForm } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled";
import { FormFields } from "../ClientDetails"; import { FormFields } from "../ClientDetails";
import { TokenLifespan } from "./TokenLifespan"; import { TokenLifespan } from "./TokenLifespan";
import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled";
type AdvancedSettingsProps = { type AdvancedSettingsProps = {
save: () => void; save: () => void;
reset: () => void; reset: () => void;
@ -36,6 +35,8 @@ export const AdvancedSettings = ({
protocol, protocol,
hasConfigureAccess, hasConfigureAccess,
}: AdvancedSettingsProps) => { }: AdvancedSettingsProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);

View file

@ -4,7 +4,7 @@ import { sortBy } from "lodash-es";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
@ -21,6 +21,8 @@ export const AuthenticationOverrides = ({
reset, reset,
hasConfigureAccess, hasConfigureAccess,
}: AuthenticationOverridesProps) => { }: AuthenticationOverridesProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [flows, setFlows] = useState<AuthenticationFlowRepresentation[]>([]); const [flows, setFlows] = useState<AuthenticationFlowRepresentation[]>([]);

View file

@ -11,8 +11,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -35,6 +34,8 @@ export const ClusteringPanel = ({
save, save,
client: { id, registeredNodes, access }, client: { id, registeredNodes, access },
}: AdvancedProps) => { }: AdvancedProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const formatDate = useFormatDate(); const formatDate = useFormatDate();

View file

@ -30,9 +30,8 @@ import {
HelpItem, HelpItem,
TextControl, TextControl,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { ForbiddenSection } from "../../ForbiddenSection"; import { ForbiddenSection } from "../../ForbiddenSection";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { ClientSelect } from "../../components/client/ClientSelect"; import { ClientSelect } from "../../components/client/ClientSelect";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -98,6 +97,8 @@ export const AuthorizationEvaluate = (props: Props) => {
}; };
const AuthorizationEvaluateContent = ({ client }: Props) => { const AuthorizationEvaluateContent = ({ client }: Props) => {
const { adminClient } = useAdminClient();
const form = useForm<EvaluateFormInputs>({ mode: "onChange" }); const form = useForm<EvaluateFormInputs>({ mode: "onChange" });
const { const {
control, control,

View file

@ -9,16 +9,18 @@ import { saveAs } from "file-saver";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextAreaControl } from "@keycloak/keycloak-ui-shared"; import { TextAreaControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { useFetch } from "../../utils/useFetch";
import { prettyPrintJSON } from "../../util"; import { prettyPrintJSON } from "../../util";
import { useFetch } from "../../utils/useFetch";
import { useParams } from "../../utils/useParams"; import { useParams } from "../../utils/useParams";
import type { ClientParams } from "../routes/Client"; import type { ClientParams } from "../routes/Client";
export const AuthorizationExport = () => { export const AuthorizationExport = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { clientId } = useParams<ClientParams>(); const { clientId } = useParams<ClientParams>();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -1,8 +1,7 @@
import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation"; import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation";
import { Alert, AlertVariant } from "@patternfly/react-core"; import { Alert, AlertVariant } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog"; import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
import type { PermissionScopeRepresentation } from "./Scopes"; import type { PermissionScopeRepresentation } from "./Scopes";
@ -25,6 +24,8 @@ export const DeleteScopeDialog = ({
open, open,
toggleDialog, toggleDialog,
}: DeleteScopeDialogProps) => { }: DeleteScopeDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -1,11 +1,10 @@
import type ResourceServerRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceServerRepresentation"; import type ResourceServerRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceServerRepresentation";
import { DescriptionList } from "@patternfly/react-core"; import { DescriptionList } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { useFetch } from "../../utils/useFetch";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useFetch } from "../../utils/useFetch";
import { toPermissionDetails } from "../routes/PermissionDetails"; import { toPermissionDetails } from "../routes/PermissionDetails";
import { toScopeDetails } from "../routes/Scope"; import { toScopeDetails } from "../routes/Scope";
import { DetailDescription, DetailDescriptionLink } from "./DetailDescription"; import { DetailDescription, DetailDescriptionLink } from "./DetailDescription";
@ -21,6 +20,8 @@ type DetailCellProps = {
}; };
export const DetailCell = ({ id, clientId, uris }: DetailCellProps) => { export const DetailCell = ({ id, clientId, uris }: DetailCellProps) => {
const { adminClient } = useAdminClient();
const { realm } = useRealm(); const { realm } = useRealm();
const [scope, setScope] = useState<Scope>(); const [scope, setScope] = useState<Scope>();
const [permissions, setPermissions] = const [permissions, setPermissions] =

View file

@ -21,8 +21,7 @@ import {
TextAreaControl, TextAreaControl,
TextControl, TextControl,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -46,6 +45,8 @@ type FormFields = PolicyRepresentation & {
}; };
export default function PermissionDetails() { export default function PermissionDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<FormFields>({ const form = useForm<FormFields>({

View file

@ -26,8 +26,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
@ -73,6 +72,8 @@ export const AuthorizationPermissions = ({
clientId, clientId,
isDisabled = false, isDisabled = false,
}: PermissionsProps) => { }: PermissionsProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -20,8 +20,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
@ -66,6 +65,8 @@ export const AuthorizationPolicies = ({
clientId, clientId,
isDisabled = false, isDisabled = false,
}: PoliciesProps) => { }: PoliciesProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -16,23 +16,23 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared"; import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import type { KeyValueType } from "../../components/key-value-form/key-value-convert";
import { KeyValueInput } from "../../components/key-value-form/KeyValueInput"; import { KeyValueInput } from "../../components/key-value-form/KeyValueInput";
import type { KeyValueType } from "../../components/key-value-form/key-value-convert";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useAccess } from "../../context/access/Access";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { useParams } from "../../utils/useParams"; import { useParams } from "../../utils/useParams";
import { toAuthorizationTab } from "../routes/AuthenticationTab"; import { toAuthorizationTab } from "../routes/AuthenticationTab";
import { ResourceDetailsParams, toResourceDetails } from "../routes/Resource"; import { ResourceDetailsParams, toResourceDetails } from "../routes/Resource";
import { ScopePicker } from "./ScopePicker"; import { ScopePicker } from "./ScopePicker";
import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAccess } from "../../context/access/Access";
import "./resource-details.css"; import "./resource-details.css";
type SubmittedResource = Omit< type SubmittedResource = Omit<
@ -43,6 +43,8 @@ type SubmittedResource = Omit<
}; };
export default function ResourceDetails() { export default function ResourceDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [client, setClient] = useState<ClientRepresentation>(); const [client, setClient] = useState<ClientRepresentation>();
const [resource, setResource] = useState<ResourceRepresentation>(); const [resource, setResource] = useState<ResourceRepresentation>();

View file

@ -19,8 +19,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
@ -54,6 +53,8 @@ export const AuthorizationResources = ({
clientId, clientId,
isDisabled = false, isDisabled = false,
}: ResourcesProps) => { }: ResourcesProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -1,3 +1,4 @@
import PolicyProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyProviderRepresentation";
import type PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation"; import type PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation";
import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation";
import type { import type {
@ -17,18 +18,16 @@ import {
useFormContext, useFormContext,
} from "react-hook-form"; } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { toPolicyDetails } from "../routes/PolicyDetails";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { toCreatePolicy } from "../routes/NewPolicy";
import { NewPolicyDialog } from "./NewPolicyDialog";
import useToggle from "../../utils/useToggle"; import useToggle from "../../utils/useToggle";
import PolicyProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyProviderRepresentation"; import { toCreatePolicy } from "../routes/NewPolicy";
import { toPolicyDetails } from "../routes/PolicyDetails";
import { toResourceDetails } from "../routes/Resource"; import { toResourceDetails } from "../routes/Resource";
import { NewPolicyDialog } from "./NewPolicyDialog";
type Type = "resources" | "policies"; type Type = "resources" | "policies";
@ -76,6 +75,8 @@ export const ResourcesPolicySelect = ({
preSelected, preSelected,
isRequired = false, isRequired = false,
}: ResourcesPolicySelectProps) => { }: ResourcesPolicySelectProps) => {
const { adminClient } = useAdminClient();
const { realm } = useRealm(); const { realm } = useRealm();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -12,7 +12,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
@ -26,6 +26,8 @@ import { DeleteScopeDialog } from "./DeleteScopeDialog";
type FormFields = Omit<ScopeRepresentation, "resources">; type FormFields = Omit<ScopeRepresentation, "resources">;
export default function ScopeDetails() { export default function ScopeDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { id, scopeId, realm } = useParams<ScopeDetailsParams>(); const { id, scopeId, realm } = useParams<ScopeDetailsParams>();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -9,8 +9,7 @@ import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
type Scope = { type Scope = {
@ -19,6 +18,8 @@ type Scope = {
}; };
export const ScopePicker = ({ clientId }: { clientId: string }) => { export const ScopePicker = ({ clientId }: { clientId: string }) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { control } = useFormContext(); const { control } = useFormContext();

View file

@ -7,8 +7,7 @@ import {
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
type ScopeSelectProps = { type ScopeSelectProps = {
@ -22,6 +21,8 @@ export const ScopeSelect = ({
resourceId, resourceId,
preSelected, preSelected,
}: ScopeSelectProps) => { }: ScopeSelectProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {

View file

@ -18,8 +18,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
import { PaginatingTableToolbar } from "../../components/table-toolbar/PaginatingTableToolbar"; import { PaginatingTableToolbar } from "../../components/table-toolbar/PaginatingTableToolbar";
@ -53,6 +52,8 @@ export const AuthorizationScopes = ({
clientId, clientId,
isDisabled = false, isDisabled = false,
}: ScopesProps) => { }: ScopesProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -11,7 +11,7 @@ import { useState } from "react";
import { Controller, FormProvider, useForm } from "react-hook-form"; import { Controller, FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup"; import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup";
@ -35,6 +35,8 @@ export type FormFields = Omit<
>; >;
export const AuthorizationSettings = ({ clientId }: { clientId: string }) => { export const AuthorizationSettings = ({ clientId }: { clientId: string }) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [resource, setResource] = useState<ResourceServerRepresentation>(); const [resource, setResource] = useState<ResourceServerRepresentation>();
const [importDialog, toggleImportDialog] = useToggle(); const [importDialog, toggleImportDialog] = useToggle();

View file

@ -6,8 +6,7 @@ import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared"; import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../../admin-client";
import { adminClient } from "../../../admin-client";
import { useFetch } from "../../../utils/useFetch"; import { useFetch } from "../../../utils/useFetch";
import useLocaleSort, { mapByKey } from "../../../utils/useLocaleSort"; import useLocaleSort, { mapByKey } from "../../../utils/useLocaleSort";
import { AddScopeDialog } from "../../scopes/AddScopeDialog"; import { AddScopeDialog } from "../../scopes/AddScopeDialog";
@ -18,6 +17,8 @@ export type RequiredIdValue = {
}; };
export const ClientScope = () => { export const ClientScope = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
control, control,

View file

@ -1,17 +1,16 @@
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
import {
FormErrorText,
HelpItem,
TextControl,
} from "@keycloak/keycloak-ui-shared";
import { Button, Checkbox, FormGroup } from "@patternfly/react-core"; import { Button, Checkbox, FormGroup } from "@patternfly/react-core";
import { MinusCircleIcon } from "@patternfly/react-icons"; import { MinusCircleIcon } from "@patternfly/react-icons";
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table"; import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import { useAdminClient } from "../../../admin-client";
FormErrorText,
HelpItem,
TextControl,
} from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../../admin-client";
import { GroupPickerDialog } from "../../../components/group/GroupPickerDialog"; import { GroupPickerDialog } from "../../../components/group/GroupPickerDialog";
import { useFetch } from "../../../utils/useFetch"; import { useFetch } from "../../../utils/useFetch";
@ -26,6 +25,8 @@ export type GroupValue = {
}; };
export const Group = () => { export const Group = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
control, control,

View file

@ -11,8 +11,7 @@ import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../../admin-client";
import { adminClient } from "../../../admin-client";
import { useAlerts } from "../../../components/alert/Alerts"; import { useAlerts } from "../../../components/alert/Alerts";
import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../../components/form/FormAccess"; import { FormAccess } from "../../../components/form/FormAccess";
@ -62,6 +61,8 @@ const COMPONENTS: {
export const isValidComponentType = (value: string) => value in COMPONENTS; export const isValidComponentType = (value: string) => value in COMPONENTS;
export default function PolicyDetails() { export default function PolicyDetails() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { id, realm, policyId, policyType } = useParams<PolicyDetailsParams>(); const { id, realm, policyId, policyType } = useParams<PolicyDetailsParams>();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -5,8 +5,7 @@ import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared"; import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../../admin-client";
import { adminClient } from "../../../admin-client";
import { DefaultSwitchControl } from "../../../components/SwitchControl"; import { DefaultSwitchControl } from "../../../components/SwitchControl";
import { AddRoleMappingModal } from "../../../components/role-mapping/AddRoleMappingModal"; import { AddRoleMappingModal } from "../../../components/role-mapping/AddRoleMappingModal";
import { Row, ServiceRole } from "../../../components/role-mapping/RoleMapping"; import { Row, ServiceRole } from "../../../components/role-mapping/RoleMapping";
@ -14,6 +13,8 @@ import { useFetch } from "../../../utils/useFetch";
import type { RequiredIdValue } from "./ClientScope"; import type { RequiredIdValue } from "./ClientScope";
export const Role = () => { export const Role = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
control, control,

View file

@ -4,15 +4,15 @@ import {
Button, Button,
FormGroup, FormGroup,
InputGroup, InputGroup,
InputGroupItem,
Split, Split,
SplitItem, SplitItem,
InputGroupItem,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PasswordInput } from "@keycloak/keycloak-ui-shared"; import { PasswordInput } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";
@ -89,6 +89,8 @@ const ExpireDateFormatter = ({ time }: { time: number }) => {
}; };
export const ClientSecret = ({ client, secret, toggle }: ClientSecretProps) => { export const ClientSecret = ({ client, secret, toggle }: ClientSecretProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -19,7 +19,7 @@ import { useState } from "react";
import { useFormContext, useWatch } from "react-hook-form"; import { useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared"; import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -40,6 +40,8 @@ export type CredentialsProps = {
}; };
export const Credentials = ({ client, save, refresh }: CredentialsProps) => { export const Credentials = ({ client, save, refresh }: CredentialsProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const clientId = client.id!; const clientId = client.id!;

View file

@ -12,8 +12,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { FileUploadForm } from "../../components/json-file-upload/FileUploadForm"; import { FileUploadForm } from "../../components/json-file-upload/FileUploadForm";
@ -34,6 +33,8 @@ import { toClients } from "../routes/Clients";
const isXml = (text: string) => text.match(/(<.[^(><.)]+>)/g); const isXml = (text: string) => text.match(/(<.[^(><.)]+>)/g);
export default function ImportForm() { export default function ImportForm() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -10,7 +10,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { NumberControl } from "@keycloak/keycloak-ui-shared"; import { NumberControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl"; import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl";
@ -20,6 +20,8 @@ import { toClients } from "../routes/Clients";
import { AccessTokenDialog } from "./AccessTokenDialog"; import { AccessTokenDialog } from "./AccessTokenDialog";
export default function CreateInitialAccessToken() { export default function CreateInitialAccessToken() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm({ mode: "onChange" }); const form = useForm({ mode: "onChange" });
const { const {

View file

@ -4,8 +4,7 @@ import { wrappable } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
@ -18,6 +17,8 @@ import useFormatDate, { FORMAT_DATE_AND_TIME } from "../../utils/useFormatDate";
import { toCreateInitialAccessToken } from "../routes/CreateInitialAccessToken"; import { toCreateInitialAccessToken } from "../routes/CreateInitialAccessToken";
export const InitialAccessTokenList = () => { export const InitialAccessTokenList = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -3,8 +3,7 @@ import { Button, Form, Modal } from "@patternfly/react-core";
import { saveAs } from "file-saver"; import { saveAs } from "file-saver";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { KeyForm, getFileExtension } from "./GenerateKeyDialog"; import { KeyForm, getFileExtension } from "./GenerateKeyDialog";
@ -21,6 +20,8 @@ export const ExportSamlKeyDialog = ({
close, close,
keyType, keyType,
}: ExportSamlKeyDialogProps) => { }: ExportSamlKeyDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -17,7 +17,7 @@ import { useState } from "react";
import { useFormContext, useWatch } from "react-hook-form"; import { useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -38,6 +38,8 @@ type KeysProps = {
const attr = "jwt.credential"; const attr = "jwt.credential";
export const Keys = ({ clientId, save, hasConfigureAccess }: KeysProps) => { export const Keys = ({ clientId, save, hasConfigureAccess }: KeysProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
control, control,

View file

@ -1,7 +1,7 @@
import { AlertVariant } from "@patternfly/react-core"; import { AlertVariant } from "@patternfly/react-core";
import { FormProvider, useFormContext } from "react-hook-form"; import { FormProvider, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog"; import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
import { KeyForm } from "./GenerateKeyDialog"; import { KeyForm } from "./GenerateKeyDialog";
@ -19,6 +19,8 @@ export const SamlImportKeyDialog = ({
attr, attr,
onClose, onClose,
}: SamlImportKeyDialogProps) => { }: SamlImportKeyDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useFormContext<SamlKeysDialogForm>(); const form = useFormContext<SamlKeysDialogForm>();
const { handleSubmit } = form; const { handleSubmit } = form;
@ -26,7 +28,7 @@ export const SamlImportKeyDialog = ({
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const submit = (form: SamlKeysDialogForm) => { const submit = (form: SamlKeysDialogForm) => {
submitForm(form, id, attr, (error) => { submitForm(adminClient, form, id, attr, (error) => {
if (error) { if (error) {
addError("importError", error); addError("importError", error);
} else { } else {

View file

@ -17,7 +17,7 @@ import { Fragment, useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormPanel, HelpItem } from "@keycloak/keycloak-ui-shared"; import { FormPanel, HelpItem } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
@ -154,6 +154,8 @@ const KeySection = ({
}; };
export const SamlKeys = ({ clientId, save }: SamlKeysProps) => { export const SamlKeys = ({ clientId, save }: SamlKeysProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [isChanged, setIsChanged] = useState<KeyTypes>(); const [isChanged, setIsChanged] = useState<KeyTypes>();
const [keyInfo, setKeyInfo] = useState<CertificateRepresentation[]>(); const [keyInfo, setKeyInfo] = useState<CertificateRepresentation[]>();

View file

@ -1,3 +1,4 @@
import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import type CertificateRepresentation from "@keycloak/keycloak-admin-client/lib/defs/certificateRepresentation"; import type CertificateRepresentation from "@keycloak/keycloak-admin-client/lib/defs/certificateRepresentation";
import type KeyStoreConfig from "@keycloak/keycloak-admin-client/lib/defs/keystoreConfig"; import type KeyStoreConfig from "@keycloak/keycloak-admin-client/lib/defs/keystoreConfig";
import { import {
@ -22,8 +23,7 @@ import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { Certificate } from "./Certificate"; import { Certificate } from "./Certificate";
import { KeyForm } from "./GenerateKeyDialog"; import { KeyForm } from "./GenerateKeyDialog";
@ -41,6 +41,7 @@ export type SamlKeysDialogForm = KeyStoreConfig & {
}; };
export const submitForm = async ( export const submitForm = async (
adminClient: KeycloakAdminClient,
form: SamlKeysDialogForm, form: SamlKeysDialogForm,
id: string, id: string,
attr: KeyTypes, attr: KeyTypes,
@ -70,6 +71,8 @@ export const SamlKeysDialog = ({
onClose, onClose,
onCancel, onCancel,
}: SamlKeysDialogProps) => { }: SamlKeysDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [type, setType] = useState(false); const [type, setType] = useState(false);
const [keys, setKeys] = useState<CertificateRepresentation>(); const [keys, setKeys] = useState<CertificateRepresentation>();
@ -82,7 +85,7 @@ export const SamlKeysDialog = ({
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const submit = (form: SamlKeysDialogForm) => { const submit = (form: SamlKeysDialogForm) => {
submitForm(form, id, attr, (error) => { submitForm(adminClient, form, id, attr, (error) => {
if (error) { if (error) {
addError("importError", error); addError("importError", error);
} else { } else {

View file

@ -3,8 +3,7 @@ import { Button, ButtonVariant, ToolbarItem } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate, useParams } from "react-router-dom"; import { Link, useNavigate, useParams } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { import {
@ -44,6 +43,8 @@ const DetailLink = (comp: ComponentRepresentation) => {
export const ClientRegistrationList = ({ export const ClientRegistrationList = ({
subType, subType,
}: ClientRegistrationListProps) => { }: ClientRegistrationListProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { subTab } = useParams<ClientRegistrationParams>(); const { subTab } = useParams<ClientRegistrationParams>();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -12,7 +12,7 @@ import { FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
@ -29,6 +29,8 @@ import {
import { toClientRegistration } from "../routes/ClientRegistration"; import { toClientRegistration } from "../routes/ClientRegistration";
export default function DetailProvider() { export default function DetailProvider() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { id, providerId, subTab } = useParams<RegistrationProviderParams>(); const { id, providerId, subTab } = useParams<RegistrationProviderParams>();
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -3,8 +3,7 @@ import { AlertVariant } from "@patternfly/react-core";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { AttributeForm } from "../../components/key-value-form/AttributeForm"; import { AttributeForm } from "../../components/key-value-form/AttributeForm";
import { RoleForm } from "../../components/role-form/RoleForm"; import { RoleForm } from "../../components/role-form/RoleForm";
@ -14,6 +13,8 @@ import { toClientRole } from "../routes/ClientRole";
import { NewRoleParams } from "../routes/NewRole"; import { NewRoleParams } from "../routes/NewRole";
export default function CreateClientRole() { export default function CreateClientRole() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const form = useForm<AttributeForm>({ mode: "onChange" }); const form = useForm<AttributeForm>({ mode: "onChange" });
const navigate = useNavigate(); const navigate = useNavigate();

View file

@ -13,8 +13,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { ChangeTypeDropdown } from "../../client-scopes/ChangeTypeDropdown"; import { ChangeTypeDropdown } from "../../client-scopes/ChangeTypeDropdown";
import { import {
SearchDropdown, SearchDropdown,
@ -73,6 +72,8 @@ const TypeSelector = ({
fineGrainedAccess, fineGrainedAccess,
...scope ...scope
}: TypeSelectorProps) => { }: TypeSelectorProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
@ -89,6 +90,7 @@ const TypeSelector = ({
onSelect={async (value) => { onSelect={async (value) => {
try { try {
await changeClientScope( await changeClientScope(
adminClient,
clientId, clientId,
scope, scope,
scope.type, scope.type,
@ -110,6 +112,8 @@ export const ClientScopes = ({
clientName, clientName,
fineGrainedAccess, fineGrainedAccess,
}: ClientScopesProps) => { }: ClientScopesProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm } = useRealm(); const { realm } = useRealm();
@ -205,6 +209,7 @@ export const ClientScopes = ({
onConfirm: async () => { onConfirm: async () => {
try { try {
await removeClientScope( await removeClientScope(
adminClient,
clientId, clientId,
selectedRows[0], selectedRows[0],
selectedRows[0].type as ClientScope, selectedRows[0].type as ClientScope,
@ -230,7 +235,12 @@ export const ClientScopes = ({
await Promise.all( await Promise.all(
scopes.map( scopes.map(
async (scope) => async (scope) =>
await addClientScope(clientId, scope.scope, scope.type!), await addClientScope(
adminClient,
clientId,
scope.scope,
scope.type!,
),
), ),
); );
addAlert(t("clientScopeSuccess"), AlertVariant.success); addAlert(t("clientScopeSuccess"), AlertVariant.success);
@ -301,6 +311,7 @@ export const ClientScopes = ({
await Promise.all( await Promise.all(
selectedRows.map((row) => selectedRows.map((row) =>
removeClientScope( removeClientScope(
adminClient,
clientId, clientId,
{ ...row }, { ...row },
row.type as ClientScope, row.type as ClientScope,

View file

@ -9,12 +9,10 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormAccess } from "../../components/form/FormAccess";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess";
import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping"; import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";
@ -25,6 +23,8 @@ type DedicatedScopeProps = {
export const DedicatedScope = ({ export const DedicatedScope = ({
client: initialClient, client: initialClient,
}: DedicatedScopeProps) => { }: DedicatedScopeProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();

View file

@ -10,8 +10,7 @@ import {
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { MapperList } from "../../client-scopes/details/MapperList"; import { MapperList } from "../../client-scopes/details/MapperList";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
@ -31,6 +30,8 @@ import { toMapper } from "../routes/Mapper";
import { DedicatedScope } from "./DedicatedScope"; import { DedicatedScope } from "./DedicatedScope";
export default function DedicatedScopes() { export default function DedicatedScopes() {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm, clientId } = useParams<DedicatedScopeDetailsParams>(); const { realm, clientId } = useParams<DedicatedScopeDetailsParams>();

View file

@ -28,16 +28,15 @@ import { useEffect, useRef, useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem, useHelp } from "@keycloak/keycloak-ui-shared"; import { HelpItem, useHelp } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
import { UserSelect } from "../../components/users/UserSelect"; import { UserSelect } from "../../components/users/UserSelect";
import { useAccess } from "../../context/access/Access";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { prettyPrintJSON } from "../../util"; import { prettyPrintJSON } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { GeneratedCodeTab } from "./GeneratedCodeTab"; import { GeneratedCodeTab } from "./GeneratedCodeTab";
import { useAccess } from "../../context/access/Access";
import "./evaluate.css"; import "./evaluate.css";
@ -116,6 +115,8 @@ const EffectiveRoles = ({
}; };
export const EvaluateScopes = ({ clientId, protocol }: EvaluateScopesProps) => { export const EvaluateScopes = ({ clientId, protocol }: EvaluateScopesProps) => {
const { adminClient } = useAdminClient();
const prefix = "openid"; const prefix = "openid";
const { t } = useTranslation(); const { t } = useTranslation();
const { enabled } = useHelp(); const { enabled } = useHelp();

View file

@ -6,8 +6,7 @@ import { InfoCircleIcon } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping"; import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping";
@ -23,6 +22,8 @@ type ServiceAccountProps = {
}; };
export const ServiceAccount = ({ client }: ServiceAccountProps) => { export const ServiceAccount = ({ client }: ServiceAccountProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm } = useRealm(); const { realm } = useRealm();

View file

@ -1,5 +1,6 @@
import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation"; import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation";
import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import { import {
DropdownItem, DropdownItem,
Select, Select,
@ -9,8 +10,6 @@ import {
import type { TFunction } from "i18next"; import type { TFunction } from "i18next";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { adminClient } from "../../admin-client";
import { toUpperCase } from "../../util"; import { toUpperCase } from "../../util";
export enum ClientScope { export enum ClientScope {
@ -96,23 +95,25 @@ export type ClientScopeDefaultOptionalType = ClientScopeRepresentation & {
}; };
export const changeScope = async ( export const changeScope = async (
adminClient: KeycloakAdminClient,
clientScope: ClientScopeDefaultOptionalType, clientScope: ClientScopeDefaultOptionalType,
changeTo: AllClientScopeType, changeTo: AllClientScopeType,
) => { ) => {
await removeScope(clientScope); await removeScope(adminClient, clientScope);
await addScope(clientScope, changeTo); await addScope(adminClient, clientScope, changeTo);
}; };
const castAdminClient = () => const castAdminClient = (adminClient: KeycloakAdminClient) =>
adminClient.clientScopes as unknown as { adminClient.clientScopes as unknown as {
[index: string]: Function; [index: string]: Function;
}; };
export const removeScope = async ( export const removeScope = async (
adminClient: KeycloakAdminClient,
clientScope: ClientScopeDefaultOptionalType, clientScope: ClientScopeDefaultOptionalType,
) => { ) => {
if (clientScope.type !== AllClientScopes.none) if (clientScope.type !== AllClientScopes.none)
await castAdminClient()[ await castAdminClient(adminClient)[
`delDefault${ `delDefault${
clientScope.type === ClientScope.optional ? "Optional" : "" clientScope.type === ClientScope.optional ? "Optional" : ""
}ClientScope` }ClientScope`
@ -122,11 +123,12 @@ export const removeScope = async (
}; };
const addScope = async ( const addScope = async (
adminClient: KeycloakAdminClient,
clientScope: ClientScopeDefaultOptionalType, clientScope: ClientScopeDefaultOptionalType,
type: AllClientScopeType, type: AllClientScopeType,
) => { ) => {
if (type !== AllClientScopes.none) if (type !== AllClientScopes.none)
await castAdminClient()[ await castAdminClient(adminClient)[
`addDefault${type === ClientScope.optional ? "Optional" : ""}ClientScope` `addDefault${type === ClientScope.optional ? "Optional" : ""}ClientScope`
]({ ]({
id: clientScope.id!, id: clientScope.id!,
@ -134,18 +136,20 @@ const addScope = async (
}; };
export const changeClientScope = async ( export const changeClientScope = async (
adminClient: KeycloakAdminClient,
clientId: string, clientId: string,
clientScope: ClientScopeRepresentation, clientScope: ClientScopeRepresentation,
type: AllClientScopeType, type: AllClientScopeType,
changeTo: ClientScopeType, changeTo: ClientScopeType,
) => { ) => {
if (type !== "none") { if (type !== "none") {
await removeClientScope(clientId, clientScope, type); await removeClientScope(adminClient, clientId, clientScope, type);
} }
await addClientScope(clientId, clientScope, changeTo); await addClientScope(adminClient, clientId, clientScope, changeTo);
}; };
export const removeClientScope = async ( export const removeClientScope = async (
adminClient: KeycloakAdminClient,
clientId: string, clientId: string,
clientScope: ClientScopeRepresentation, clientScope: ClientScopeRepresentation,
type: ClientScope, type: ClientScope,
@ -159,6 +163,7 @@ export const removeClientScope = async (
}; };
export const addClientScope = async ( export const addClientScope = async (
adminClient: KeycloakAdminClient,
clientId: string, clientId: string,
clientScope: ClientScopeRepresentation, clientScope: ClientScopeRepresentation,
type: ClientScopeType, type: ClientScopeType,

View file

@ -4,8 +4,7 @@ import { SelectProps, SelectVariant } from "@patternfly/react-core/deprecated";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import type { ComponentProps } from "../dynamic/components"; import type { ComponentProps } from "../dynamic/components";
@ -20,6 +19,8 @@ export const ClientSelect = ({
required = false, required = false,
variant = SelectVariant.typeahead, variant = SelectVariant.typeahead,
}: ClientSelectProps) => { }: ClientSelectProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [clients, setClients] = useState<ClientRepresentation[]>([]); const [clients, setClients] = useState<ClientRepresentation[]>([]);

View file

@ -16,8 +16,7 @@ import { saveAs } from "file-saver";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem, useHelp } from "@keycloak/keycloak-ui-shared"; import { HelpItem, useHelp } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { addTrailingSlash, prettyPrintJSON } from "../../util"; import { addTrailingSlash, prettyPrintJSON } from "../../util";
@ -38,6 +37,8 @@ export const DownloadDialog = ({
toggleDialog, toggleDialog,
protocol = "openid-connect", protocol = "openid-connect",
}: DownloadDialogProps) => { }: DownloadDialogProps) => {
const { adminClient } = useAdminClient();
const { realm } = useRealm(); const { realm } = useRealm();
const { t } = useTranslation(); const { t } = useTranslation();
const { enabled } = useHelp(); const { enabled } = useHelp();

View file

@ -4,8 +4,7 @@ import { useState } from "react";
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared"; import { FormErrorText, HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { KeySelect } from "../key-value-form/KeySelect"; import { KeySelect } from "../key-value-form/KeySelect";
import { convertToName } from "./DynamicComponents"; import { convertToName } from "./DynamicComponents";
@ -17,6 +16,8 @@ export const UserProfileAttributeListComponent = ({
helpText, helpText,
required = false, required = false,
}: ComponentProps) => { }: ComponentProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
formState: { errors }, formState: { errors },

View file

@ -20,7 +20,7 @@ import {
import { AngleRightIcon } from "@patternfly/react-icons"; import { AngleRightIcon } from "@patternfly/react-icons";
import { Fragment, useState } from "react"; import { Fragment, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { adminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { ListEmptyState } from "../list-empty-state/ListEmptyState"; import { ListEmptyState } from "../list-empty-state/ListEmptyState";
import { PaginatingTableToolbar } from "../table-toolbar/PaginatingTableToolbar"; import { PaginatingTableToolbar } from "../table-toolbar/PaginatingTableToolbar";
@ -53,6 +53,8 @@ export const GroupPickerDialog = ({
onClose, onClose,
onConfirm, onConfirm,
}: GroupPickerDialogProps) => { }: GroupPickerDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedRows, setSelectedRows] = useState<SelectableGroup[]>([]); const [selectedRows, setSelectedRows] = useState<SelectableGroup[]>([]);

View file

@ -21,8 +21,7 @@ import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client";
import { adminClient } from "../../admin-client";
import { toPermissionDetails } from "../../clients/routes/PermissionDetails"; import { toPermissionDetails } from "../../clients/routes/PermissionDetails";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
@ -45,6 +44,8 @@ type PermissionsTabProps = {
}; };
export const PermissionsTab = ({ id, type }: PermissionsTabProps) => { export const PermissionsTab = ({ id, type }: PermissionsTabProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { realm } = useRealm(); const { realm } = useRealm();

Some files were not shown because too many files have changed in this diff Show more