refacored the keys tab removed duplication (#2146)
This commit is contained in:
parent
6e0414c557
commit
5c64ab6a4a
46 changed files with 1462 additions and 4351 deletions
|
@ -0,0 +1,25 @@
|
|||
export default class KeysTab {
|
||||
private readonly keysTab = "rs-keys-tab";
|
||||
private readonly providersTab = "rs-providers-tab";
|
||||
private readonly addProviderDropdown = "addProviderDropdown";
|
||||
|
||||
goToKeysTab() {
|
||||
cy.findByTestId(this.keysTab).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
goToProvidersTab() {
|
||||
this.goToKeysTab();
|
||||
cy.findByTestId(this.providersTab).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
addProvider(provider: string) {
|
||||
cy.findByTestId(this.addProviderDropdown).click();
|
||||
cy.findByTestId(`option-${provider}`).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -68,15 +68,15 @@ export default class RealmSettingsPage {
|
|||
enableStartTlsCheck = "enable-start-tls";
|
||||
addProviderDropdown = "addProviderDropdown";
|
||||
addProviderButton = "add-provider-button";
|
||||
displayName = "display-name-input";
|
||||
displayName = "name-input";
|
||||
enableEvents = "eventsEnabled";
|
||||
eventsUserSave = "save-user";
|
||||
enableAdminEvents = "adminEventsEnabled";
|
||||
eventsAdminSave = "save-admin";
|
||||
eventTypeColumn = 'tbody > tr > [data-label="Event saved type"]';
|
||||
filterSelectMenu = ".kc-filter-type-select";
|
||||
passiveKeysOption = "passive-keys-option";
|
||||
disabledKeysOption = "disabled-keys-option";
|
||||
passiveKeysOption = "PASSIVE-option";
|
||||
disabledKeysOption = "DISABLED-option";
|
||||
testConnectionButton = "test-connection-button";
|
||||
modalTestConnectionButton = "modal-test-connection-button";
|
||||
emailAddressInput = "email-address-input";
|
||||
|
|
|
@ -2,7 +2,10 @@ import React, { ReactNode, useMemo, useRef, useState } from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { get } from "lodash-es";
|
||||
import {
|
||||
ActionsColumn,
|
||||
IAction,
|
||||
TableComposable,
|
||||
TableComposableProps,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
|
@ -17,10 +20,11 @@ export type Field<T> = {
|
|||
cellRenderer?: (row: T) => ReactNode;
|
||||
};
|
||||
|
||||
type DraggableTableProps<T> = {
|
||||
type DraggableTableProps<T> = Omit<TableComposableProps, "data" | "ref"> & {
|
||||
keyField: string;
|
||||
columns: Field<T>[];
|
||||
data: T[];
|
||||
actions?: IAction[];
|
||||
onDragFinish: (dragged: string, newOrder: string[]) => void;
|
||||
};
|
||||
|
||||
|
@ -28,7 +32,9 @@ export function DraggableTable<T>({
|
|||
keyField,
|
||||
columns,
|
||||
data,
|
||||
actions,
|
||||
onDragFinish,
|
||||
...props
|
||||
}: DraggableTableProps<T>) {
|
||||
const { t } = useTranslation("authentication");
|
||||
const bodyRef = useRef<HTMLTableSectionElement>(null);
|
||||
|
@ -169,6 +175,7 @@ export function DraggableTable<T>({
|
|||
<TableComposable
|
||||
aria-label="Draggable table"
|
||||
className={state.dragging ? styles.modifiers.dragOver : ""}
|
||||
{...props}
|
||||
>
|
||||
<Thead>
|
||||
<Tr>
|
||||
|
@ -208,6 +215,11 @@ export function DraggableTable<T>({
|
|||
: get(row, column.name)}
|
||||
</Td>
|
||||
))}
|
||||
{actions && (
|
||||
<Td isActionCell>
|
||||
<ActionsColumn items={actions} rowData={row} />
|
||||
</Td>
|
||||
)}
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, KeyboardEvent } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
FormGroup,
|
||||
|
@ -189,7 +189,7 @@ export const AuthorizationEvaluate = ({
|
|||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: any) => {
|
||||
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
onSearch();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import React, {
|
|||
FunctionComponent,
|
||||
ReactNode,
|
||||
useState,
|
||||
KeyboardEvent,
|
||||
} from "react";
|
||||
import {
|
||||
Toolbar,
|
||||
|
@ -55,7 +56,7 @@ export const TableToolbar: FunctionComponent<TableToolbarProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: any) => {
|
||||
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
onSearch();
|
||||
}
|
||||
|
|
|
@ -1,347 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Form,
|
||||
FormGroup,
|
||||
Modal,
|
||||
ModalVariant,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { KEY_PROVIDER_TYPE } from "../util";
|
||||
|
||||
type JavaKeystoreModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const JavaKeystoreModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: // save,
|
||||
JavaKeystoreModalProps) => {
|
||||
const { t } = useTranslation("groups");
|
||||
const serverInfo = useServerInfo();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const { handleSubmit, control } = useForm({});
|
||||
const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] =
|
||||
useState(false);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh();
|
||||
} catch (error) {
|
||||
addError("groups:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
actions={[
|
||||
<Button
|
||||
data-testid="add-provider-button"
|
||||
key="confirm"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
form="add-provider"
|
||||
>
|
||||
{t("common:Add")}
|
||||
</Button>,
|
||||
<Button
|
||||
id="modal-cancel"
|
||||
data-testid="cancel"
|
||||
key="cancel"
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => {
|
||||
handleModalToggle!();
|
||||
}}
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save!)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("consoleDisplayName")}
|
||||
fieldId="kc-console-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:displayName"
|
||||
fieldLabelId="realm-settings:consoleDisplayName"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
}}
|
||||
data-testid="display-name-input"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-active"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{providerType === "java-keystore" && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={control}
|
||||
defaultValue={["RS256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={() =>
|
||||
setIsEllipticCurveDropdownOpen(
|
||||
!isEllipticCurveDropdownOpen
|
||||
)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value + ""]);
|
||||
setIsEllipticCurveDropdownOpen(false);
|
||||
}}
|
||||
selections={[value + ""]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isEllipticCurveDropdownOpen}
|
||||
placeholderText="Select one..."
|
||||
data-testid="select-algorithm"
|
||||
>
|
||||
{allComponentTypes[3].properties[3].options!.map(
|
||||
(p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`algorithm-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystore")}
|
||||
fieldId="kc-login-theme"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystore"
|
||||
fieldLabelId="realm-settings:keystore"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystore"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keystore")}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystorePassword")}
|
||||
fieldId="kc-login-theme"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystorePassword"
|
||||
fieldLabelId="realm-settings:keystorePassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystorePassword"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyAlias")}
|
||||
fieldId="kc-login-theme"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyAlias"
|
||||
fieldLabelId="realm-settings:keyAlias"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyAlias"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyPassword")}
|
||||
fieldId="kc-login-theme"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyPassword"
|
||||
fieldLabelId="realm-settings:keyPassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyPassword"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,479 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
DataList,
|
||||
DataListAction,
|
||||
DataListCell,
|
||||
DataListControl,
|
||||
DataListDragButton,
|
||||
DataListItem,
|
||||
DataListItemCells,
|
||||
DataListItemRow,
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownPosition,
|
||||
DropdownToggle,
|
||||
InputGroup,
|
||||
KebabToggle,
|
||||
PageSection,
|
||||
TextInput,
|
||||
Toolbar,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
Tooltip,
|
||||
} from "@patternfly/react-core";
|
||||
import { SearchIcon } from "@patternfly/react-icons";
|
||||
|
||||
import type { KeyMetadataRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/keyMetadataRepresentation";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { Link, useRouteMatch } from "react-router-dom";
|
||||
import { AESGeneratedModal } from "./key-providers/aes-generated/AESGeneratedModal";
|
||||
import { JavaKeystoreModal } from "./key-providers/java-keystore/JavaKeystoreModal";
|
||||
import { HMACGeneratedModal } from "./key-providers/hmac-generated/HMACGeneratedModal";
|
||||
import { ECDSAGeneratedModal } from "./key-providers/ecdsa-generated/ECDSAGeneratedModal";
|
||||
import { RSAModal } from "./RSAModal";
|
||||
import { RSAEncGeneratedModal } from "./key-providers/rsa-enc-generated/RSAEncGeneratedModal";
|
||||
import { RSAGeneratedModal } from "./key-providers/rsa-generated/RSAGeneratedModal";
|
||||
import { KEY_PROVIDER_TYPE } from "../util";
|
||||
|
||||
type ComponentData = KeyMetadataRepresentation & {
|
||||
id?: string;
|
||||
providerDescription?: string;
|
||||
name?: string;
|
||||
toggleHidden?: boolean;
|
||||
config?: any;
|
||||
parentId?: string;
|
||||
};
|
||||
|
||||
type KeysTabInnerProps = {
|
||||
components: ComponentData[];
|
||||
realmComponents: ComponentRepresentation[];
|
||||
keyProviderComponentTypes: ComponentTypeRepresentation[];
|
||||
refresh: () => void;
|
||||
};
|
||||
|
||||
export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useRealm();
|
||||
const { url } = useRouteMatch();
|
||||
|
||||
const [id, setId] = useState("");
|
||||
|
||||
const [searchVal, setSearchVal] = useState("");
|
||||
const [filteredComponents, setFilteredComponents] = useState<ComponentData[]>(
|
||||
[]
|
||||
);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const providerTypes = (
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? []
|
||||
).map((item) => item.id);
|
||||
|
||||
const [itemOrder, setItemOrder] = useState<string[]>([]);
|
||||
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
|
||||
|
||||
const [defaultConsoleDisplayName, setDefaultConsoleDisplayName] =
|
||||
useState("");
|
||||
|
||||
const [selectedComponent, setSelectedComponent] =
|
||||
useState<ComponentRepresentation>();
|
||||
|
||||
const [liveText, setLiveText] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const itemIds = components.map((component) => component.id!);
|
||||
setItemOrder(["data", ...itemIds]);
|
||||
}, [components, searchVal]);
|
||||
|
||||
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
|
||||
titleKey: "realm-settings:deleteProviderTitle",
|
||||
messageKey: t("deleteProviderConfirm") + selectedComponent?.name + "?",
|
||||
continueButtonLabel: "common:delete",
|
||||
continueButtonVariant: ButtonVariant.danger,
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await adminClient.components.del({
|
||||
id: selectedComponent!.id!,
|
||||
realm: realm,
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
addAlert(t("deleteProviderSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("realm-settings:deleteProviderError", error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const onDragStart = async (id: string) => {
|
||||
setLiveText(t("common:onDragStart", { item: id }));
|
||||
setId(id);
|
||||
};
|
||||
|
||||
const onDragMove = () => {
|
||||
setLiveText(t("common:onDragMove", { item: id }));
|
||||
};
|
||||
|
||||
const onDragCancel = () => {
|
||||
setLiveText(t("common:onDragCancel"));
|
||||
};
|
||||
|
||||
const onDragFinish = async (itemOrder: string[]) => {
|
||||
setItemOrder(itemOrder);
|
||||
setLiveText(t("common:onDragFinish"));
|
||||
const updateAll = components.map((component: ComponentData) => {
|
||||
const componentToSave = { ...component };
|
||||
delete componentToSave.providerDescription;
|
||||
|
||||
return adminClient.components.update(
|
||||
{ id: component.id! },
|
||||
{
|
||||
...componentToSave,
|
||||
config: {
|
||||
priority: [
|
||||
(
|
||||
itemOrder.length -
|
||||
itemOrder.indexOf(component.id!) +
|
||||
100
|
||||
).toString(),
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(updateAll);
|
||||
refresh();
|
||||
addAlert(
|
||||
t("realm-settings:saveProviderListSuccess"),
|
||||
AlertVariant.success
|
||||
);
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const onSearch = () => {
|
||||
if (searchVal !== "") {
|
||||
setSearchVal(searchVal);
|
||||
const x = components.filter((v) => {
|
||||
return v.name?.includes(searchVal) || v.providerId?.includes(searchVal);
|
||||
});
|
||||
setFilteredComponents(x);
|
||||
} else {
|
||||
setSearchVal("");
|
||||
setFilteredComponents(components);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: any) => {
|
||||
if (e.key === "Enter") {
|
||||
onSearch();
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (value: string) => {
|
||||
setSearchVal(value);
|
||||
};
|
||||
|
||||
const handleModalToggle = () => {
|
||||
setIsCreateModalOpen(!isCreateModalOpen);
|
||||
};
|
||||
|
||||
const [actionListOpen, setActionListOpen] = useState<boolean[]>(
|
||||
components.map(() => false)
|
||||
);
|
||||
const toggleActionList = (index: number) => {
|
||||
actionListOpen[index] = !actionListOpen[index];
|
||||
setActionListOpen([...actionListOpen]);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{defaultConsoleDisplayName === "aes-generated" && (
|
||||
<AESGeneratedModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "ecdsa-generated" && (
|
||||
<ECDSAGeneratedModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "hmac-generated" && (
|
||||
<HMACGeneratedModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "java-keystore" && (
|
||||
<JavaKeystoreModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "rsa" && (
|
||||
<RSAModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "rsa-generated" && (
|
||||
<RSAGeneratedModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
{defaultConsoleDisplayName === "rsa-enc-generated" && (
|
||||
<RSAEncGeneratedModal
|
||||
handleModalToggle={handleModalToggle}
|
||||
providerType={defaultConsoleDisplayName}
|
||||
refresh={refresh}
|
||||
open={isCreateModalOpen}
|
||||
/>
|
||||
)}
|
||||
<DeleteConfirm />
|
||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||
<Toolbar>
|
||||
<ToolbarGroup className="providers-toolbar">
|
||||
<ToolbarItem>
|
||||
<InputGroup>
|
||||
<TextInput
|
||||
name={"inputGroupName"}
|
||||
id={"inputGroupName"}
|
||||
type="search"
|
||||
aria-label={t("common:search")}
|
||||
placeholder={t("common:search")}
|
||||
onChange={handleInputChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<Button
|
||||
variant={ButtonVariant.control}
|
||||
aria-label={t("common:search")}
|
||||
>
|
||||
<SearchIcon />
|
||||
</Button>
|
||||
</InputGroup>
|
||||
</ToolbarItem>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
data-testid="addProviderDropdown"
|
||||
className="add-provider-dropdown"
|
||||
isOpen={providerDropdownOpen}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
onToggle={(val) => setProviderDropdownOpen(val)}
|
||||
isPrimary
|
||||
>
|
||||
{t("realm-settings:addProvider")}
|
||||
</DropdownToggle>
|
||||
}
|
||||
dropdownItems={[
|
||||
providerTypes.map((item) => (
|
||||
<DropdownItem
|
||||
onClick={() => {
|
||||
handleModalToggle();
|
||||
|
||||
setProviderDropdownOpen(false);
|
||||
setDefaultConsoleDisplayName(item);
|
||||
}}
|
||||
data-testid={`option-${item}`}
|
||||
key={item}
|
||||
>
|
||||
{item}
|
||||
</DropdownItem>
|
||||
)),
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
<DataList
|
||||
aria-label={t("common:groups")}
|
||||
onDragFinish={onDragFinish}
|
||||
onDragStart={onDragStart}
|
||||
onDragMove={onDragMove}
|
||||
onDragCancel={onDragCancel}
|
||||
itemOrder={itemOrder}
|
||||
isCompact
|
||||
>
|
||||
<DataListItem aria-labelledby={"aria"} id="data" key="data">
|
||||
<DataListItemRow className="test" data-testid="data-list-row">
|
||||
<DataListDragButton
|
||||
className="header-drag-button"
|
||||
aria-label="Reorder"
|
||||
aria-describedby={t("common-help:dragHelp")}
|
||||
aria-pressed="false"
|
||||
isDisabled
|
||||
/>
|
||||
<DataListItemCells
|
||||
className="data-list-cells"
|
||||
dataListCells={[
|
||||
<DataListCell className="name" key="name">
|
||||
<>{t("realm-settings:name")}</>
|
||||
</DataListCell>,
|
||||
<DataListCell className="provider" key="provider">
|
||||
<>{t("realm-settings:provider")}</>
|
||||
</DataListCell>,
|
||||
<DataListCell
|
||||
className="provider-description"
|
||||
key="provider-description"
|
||||
>
|
||||
<>{t("realm-settings:providerDescription")}</>
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
</DataListItemRow>
|
||||
</DataListItem>
|
||||
{(filteredComponents.length === 0
|
||||
? components
|
||||
: filteredComponents
|
||||
).map((component, idx) => (
|
||||
<DataListItem
|
||||
draggable
|
||||
aria-labelledby={"aria"}
|
||||
key={component.id}
|
||||
id={component.id}
|
||||
>
|
||||
<DataListItemRow data-testid="data-list-row">
|
||||
<DataListControl>
|
||||
<Tooltip content={t("dragInstruction")} position="top">
|
||||
<DataListDragButton
|
||||
className="kc-row-drag-button"
|
||||
aria-label="Reorder"
|
||||
aria-describedby={t("common-help:dragHelp")}
|
||||
aria-pressed="false"
|
||||
/>
|
||||
</Tooltip>
|
||||
</DataListControl>
|
||||
<DataListItemCells
|
||||
dataListCells={[
|
||||
<DataListCell
|
||||
data-testid="provider-name"
|
||||
key={`name-${idx}`}
|
||||
>
|
||||
<Link
|
||||
key={component.name}
|
||||
data-testid="provider-name-link"
|
||||
to={`${url}/${component.id}/${component.providerId}/settings`}
|
||||
>
|
||||
{component.name}
|
||||
</Link>
|
||||
</DataListCell>,
|
||||
<DataListCell key={`providerId-${idx}`}>
|
||||
{component.providerId}
|
||||
</DataListCell>,
|
||||
<DataListCell key={`providerDescription-${idx}`}>
|
||||
{component.providerDescription}
|
||||
</DataListCell>,
|
||||
<DataListAction
|
||||
aria-labelledby="data-list-action"
|
||||
aria-label="Actions"
|
||||
isPlainButtonAction
|
||||
key={`data-action-list-${idx}`}
|
||||
id={`data-action-list-${idx}`}
|
||||
>
|
||||
<Dropdown
|
||||
isPlain
|
||||
position={DropdownPosition.right}
|
||||
isOpen={actionListOpen[idx]}
|
||||
toggle={
|
||||
<KebabToggle
|
||||
data-testid="provider-action"
|
||||
onToggle={() => {
|
||||
toggleActionList(idx);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
dropdownItems={[
|
||||
<DropdownItem
|
||||
key="action"
|
||||
component="button"
|
||||
data-testid="delete-action"
|
||||
onClick={() => {
|
||||
setSelectedComponent(component);
|
||||
toggleDeleteDialog();
|
||||
toggleActionList(idx);
|
||||
}}
|
||||
>
|
||||
{t("common:delete")}
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
</DataListAction>,
|
||||
]}
|
||||
/>
|
||||
</DataListItemRow>
|
||||
</DataListItem>
|
||||
))}
|
||||
</DataList>
|
||||
<div className="pf-screen-reader" aria-live="assertive">
|
||||
{liveText}
|
||||
</div>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
type KeysProps = {
|
||||
realmComponents: ComponentRepresentation[];
|
||||
keyProviderComponentTypes: ComponentTypeRepresentation[];
|
||||
refresh: () => void;
|
||||
};
|
||||
|
||||
export const KeysProvidersTab = ({
|
||||
keyProviderComponentTypes,
|
||||
realmComponents,
|
||||
refresh,
|
||||
...props
|
||||
}: KeysProps) => {
|
||||
return (
|
||||
<KeysTabInner
|
||||
components={realmComponents.map((component) => {
|
||||
const provider = keyProviderComponentTypes.find(
|
||||
(componentType: ComponentTypeRepresentation) =>
|
||||
component.providerId === componentType.id
|
||||
);
|
||||
|
||||
return {
|
||||
...component,
|
||||
providerDescription: provider?.helpText,
|
||||
};
|
||||
})}
|
||||
keyProviderComponentTypes={keyProviderComponentTypes}
|
||||
refresh={refresh}
|
||||
realmComponents={realmComponents}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,286 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Form,
|
||||
FormGroup,
|
||||
Modal,
|
||||
ModalVariant,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { KEY_PROVIDER_TYPE } from "../util";
|
||||
|
||||
type RSAGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const RSAGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: RSAGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const { handleSubmit, control } = useForm({});
|
||||
const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false);
|
||||
const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh();
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
actions={[
|
||||
<Button
|
||||
data-testid="add-provider-button"
|
||||
key="confirm"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
form="add-provider"
|
||||
>
|
||||
{t("common:Add")}
|
||||
</Button>,
|
||||
<Button
|
||||
id="modal-cancel"
|
||||
data-testid="cancel"
|
||||
key="cancel"
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => {
|
||||
handleModalToggle!();
|
||||
}}
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save!)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("consoleDisplayName")}
|
||||
fieldId="kc-console-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:displayName"
|
||||
fieldLabelId="realm-settings:loginTheme"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
}}
|
||||
data-testid="display-name-input"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings:realm-settings-help:enabled"
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-active"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{providerType === "rsa-generated" && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={control}
|
||||
defaultValue={["RS256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-algorithm"
|
||||
onToggle={() =>
|
||||
setIsRSAalgDropdownOpen(!isRSAalgDropdownOpen)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value + ""]);
|
||||
setIsRSAalgDropdownOpen(false);
|
||||
}}
|
||||
selections={[value + ""]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isRSAalgDropdownOpen}
|
||||
data-testid="select-rsa-algorithm"
|
||||
>
|
||||
{allComponentTypes[5].properties[3].options!.map(
|
||||
(p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`rsa-algorithm-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("AESKeySize")}
|
||||
fieldId="kc-aes-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:AESKeySize"
|
||||
fieldLabelId="realm-settings:AESKeySize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.secretSize"
|
||||
control={control}
|
||||
defaultValue={["2048"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-keysize"
|
||||
onToggle={() =>
|
||||
setIsKeySizeDropdownOpen(!isKeySizeDropdownOpen)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value + ""]);
|
||||
setIsKeySizeDropdownOpen(false);
|
||||
}}
|
||||
selections={[value + ""]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("keySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{allComponentTypes[5].properties[4].options!.map(
|
||||
(item, idx) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={`rsa-generated-key-size-${idx}`}
|
||||
value={item}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,319 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
FileUpload,
|
||||
Form,
|
||||
FormGroup,
|
||||
Modal,
|
||||
ModalVariant,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { KEY_PROVIDER_TYPE } from "../util";
|
||||
|
||||
type RSAModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const RSAModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: RSAModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const { handleSubmit, control } = useForm({});
|
||||
const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false);
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const [keyFileName, setKeyFileName] = useState("");
|
||||
const [certificateFileName, setCertificateFileName] = useState("");
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
actions={[
|
||||
<Button
|
||||
data-testid="add-provider-button"
|
||||
key="confirm"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
form="add-provider"
|
||||
>
|
||||
{t("common:Add")}
|
||||
</Button>,
|
||||
<Button
|
||||
id="modal-cancel"
|
||||
data-testid="cancel"
|
||||
key="cancel"
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => {
|
||||
handleModalToggle!();
|
||||
}}
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit(save!)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("consoleDisplayName")}
|
||||
fieldId="kc-console-display-name"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:displayName"
|
||||
fieldLabelId="realm-settings:consoleDisplayName"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
}}
|
||||
data-testid="display-name-input"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-active"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value + ""]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{providerType === "rsa" && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="algorithm"
|
||||
defaultValue=""
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-algorithm"
|
||||
onToggle={() =>
|
||||
setIsRSAalgDropdownOpen(!isRSAalgDropdownOpen)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsRSAalgDropdownOpen(false);
|
||||
}}
|
||||
selections={[value + ""]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isRSAalgDropdownOpen}
|
||||
data-testid="select-rsa-algorithm"
|
||||
>
|
||||
{allComponentTypes[4].properties[3].options!.map(
|
||||
(p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`rsa-algorithm-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("privateRSAKey")}
|
||||
fieldId="kc-private-rsa-key"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:privateRSAKey"
|
||||
fieldLabelId="realm-settings:privateRSAKey"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.privateKey"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<FileUpload
|
||||
id="importPrivateKey"
|
||||
type="text"
|
||||
value={value[0]}
|
||||
filenamePlaceholder="Upload a PEM file or paste key below"
|
||||
filename={keyFileName}
|
||||
onChange={(value, fileName) => {
|
||||
setKeyFileName(fileName);
|
||||
onChange([value]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("x509Certificate")}
|
||||
fieldId="kc-aes-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:x509Certificate"
|
||||
fieldLabelId="realm-settings:x509Certificate"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.certificate"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<FileUpload
|
||||
id="importCertificate"
|
||||
type="text"
|
||||
value={value[0]}
|
||||
filenamePlaceholder="Upload a PEM file or paste key below"
|
||||
filename={certificateFileName}
|
||||
onChange={(value, fileName) => {
|
||||
setCertificateFileName(fileName);
|
||||
onChange([value]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,63 +1,27 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { KEY_PROVIDER_TYPE } from "../util";
|
||||
import { RealmSettingsTabs } from "./RealmSettingsTabs";
|
||||
|
||||
const sortByPriority = (components: ComponentRepresentation[]) => {
|
||||
const sortedComponents = [...components].sort((a, b) => {
|
||||
const priorityA = Number(a.config?.priority);
|
||||
const priorityB = Number(b.config?.priority);
|
||||
|
||||
return (
|
||||
(!isNaN(priorityB) ? priorityB : 0) - (!isNaN(priorityA) ? priorityA : 0)
|
||||
);
|
||||
});
|
||||
|
||||
return sortedComponents;
|
||||
};
|
||||
|
||||
export default function RealmSettingsSection() {
|
||||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||
const [realmComponents, setRealmComponents] =
|
||||
useState<ComponentRepresentation[]>();
|
||||
const [key, setKey] = useState(0);
|
||||
|
||||
const refresh = () => {
|
||||
setKey(key + 1);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
const realm = await adminClient.realms.findOne({ realm: realmName });
|
||||
const realmComponents = await adminClient.components.find({
|
||||
type: KEY_PROVIDER_TYPE,
|
||||
realm: realmName,
|
||||
});
|
||||
useFetch(() => adminClient.realms.findOne({ realm: realmName }), setRealm, [
|
||||
key,
|
||||
]);
|
||||
|
||||
return { realm, realmComponents };
|
||||
},
|
||||
({ realm, realmComponents }) => {
|
||||
setRealmComponents(sortByPriority(realmComponents));
|
||||
setRealm(realm);
|
||||
},
|
||||
[key]
|
||||
);
|
||||
|
||||
if (!realm || !realmComponents) {
|
||||
if (!realm) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
return (
|
||||
<RealmSettingsTabs
|
||||
realm={realm}
|
||||
refresh={refresh}
|
||||
realmComponents={realmComponents}
|
||||
/>
|
||||
);
|
||||
return <RealmSettingsTabs realm={realm} refresh={refresh} />;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import {
|
||||
|
@ -24,20 +23,16 @@ import { useRealm } from "../context/realm-context/RealmContext";
|
|||
import { useRealms } from "../context/RealmsContext";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import {
|
||||
convertFormValuesToObject,
|
||||
convertToFormValues,
|
||||
KEY_PROVIDER_TYPE,
|
||||
toUpperCase,
|
||||
} from "../util";
|
||||
|
||||
import { RealmSettingsEmailTab } from "./EmailTab";
|
||||
import { EventsTab } from "./event-config/EventsTab";
|
||||
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
||||
import { KeysListTab } from "./KeysListTab";
|
||||
import { KeysProvidersTab } from "./KeysProvidersTab";
|
||||
import { RealmSettingsLoginTab } from "./LoginTab";
|
||||
import { SecurityDefences } from "./security-defences/SecurityDefences";
|
||||
import { RealmSettingsSessionsTab } from "./SessionsTab";
|
||||
|
@ -57,7 +52,7 @@ import helpUrls from "../help-urls";
|
|||
import { UserProfileTab } from "./user-profile/UserProfileTab";
|
||||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
import { ClientPoliciesTab, toClientPolicies } from "./routes/ClientPolicies";
|
||||
import { KeySubTab, toKeysTab } from "./routes/KeysTab";
|
||||
import { KeysTab } from "./keys/KeysTab";
|
||||
|
||||
type RealmSettingsHeaderProps = {
|
||||
onChange: (value: boolean) => void;
|
||||
|
@ -166,12 +161,10 @@ const RealmSettingsHeader = ({
|
|||
type RealmSettingsTabsProps = {
|
||||
realm: RealmRepresentation;
|
||||
refresh: () => void;
|
||||
realmComponents: ComponentRepresentation[];
|
||||
};
|
||||
|
||||
export const RealmSettingsTabs = ({
|
||||
realm,
|
||||
realmComponents,
|
||||
refresh,
|
||||
}: RealmSettingsTabsProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
@ -182,9 +175,6 @@ export const RealmSettingsTabs = ({
|
|||
const history = useHistory();
|
||||
const isFeatureEnabled = useIsFeatureEnabled();
|
||||
|
||||
const kpComponentTypes =
|
||||
useServerInfo().componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const form = useForm({ mode: "onChange", shouldUnregister: false });
|
||||
const { control, getValues, setValue, reset: resetForm } = form;
|
||||
|
||||
|
@ -247,11 +237,6 @@ export const RealmSettingsTabs = ({
|
|||
history,
|
||||
});
|
||||
|
||||
const keysRoute = (tab: KeySubTab) =>
|
||||
routableTab({
|
||||
to: toKeysTab({ realm: realmName, tab }),
|
||||
history,
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<Controller
|
||||
|
@ -321,32 +306,7 @@ export const RealmSettingsTabs = ({
|
|||
data-testid="rs-keys-tab"
|
||||
{...route("keys")}
|
||||
>
|
||||
<RoutableTabs
|
||||
defaultLocation={toKeysTab({ realm: realmName, tab: "list" })}
|
||||
>
|
||||
<Tab
|
||||
id="keysList"
|
||||
data-testid="rs-keys-list-tab"
|
||||
aria-label="keys-list-subtab"
|
||||
title={<TabTitleText>{t("keysList")}</TabTitleText>}
|
||||
{...keysRoute("list")}
|
||||
>
|
||||
<KeysListTab realmComponents={realmComponents} />
|
||||
</Tab>
|
||||
<Tab
|
||||
id="providers"
|
||||
data-testid="rs-providers-tab"
|
||||
aria-label="rs-providers-tab"
|
||||
title={<TabTitleText>{t("providers")}</TabTitleText>}
|
||||
{...keysRoute("providers")}
|
||||
>
|
||||
<KeysProvidersTab
|
||||
realmComponents={realmComponents}
|
||||
keyProviderComponentTypes={kpComponentTypes}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Tab>
|
||||
</RoutableTabs>
|
||||
<KeysTab />
|
||||
</Tab>
|
||||
<Tab
|
||||
title={<TabTitleText>{t("events")}</TabTitleText>}
|
||||
|
|
|
@ -1,336 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type AESGeneratedFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType: string;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const AESGeneratedForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
}: AESGeneratedFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false);
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const aesSecretSizeOptions = allComponentTypes[0].properties[3].options;
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={
|
||||
value[0] === "true"
|
||||
? "internationalization-enabled"
|
||||
: "internationalization-disabled"
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("AESKeySize")}
|
||||
fieldId="kc-aes-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:AESKeySize"
|
||||
fieldLabelId="realm-settings:AESKeySize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.secretSize"
|
||||
control={form.control}
|
||||
defaultValue={["16"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-aes-keysize"
|
||||
onToggle={() => setIsKeySizeDropdownOpen(!isKeySizeDropdownOpen)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsKeySizeDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("aesKeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{aesSecretSizeOptions?.map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-AESform-buttons">
|
||||
<Button
|
||||
className="kc-AESform-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-AESform-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function AESGeneratedSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<AESGeneratedForm providerType={providerId!} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AESGeneratedForm } from "./AESGeneratedForm";
|
||||
|
||||
type AESGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const AESGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: AESGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<AESGeneratedForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,327 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type ECDSAGeneratedFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType?: string;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const ECDSAGeneratedForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
}: ECDSAGeneratedFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false);
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const ecdsaEllipticCurveOptions = allComponentTypes[1].properties[3].options;
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="client-scopes:providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "enabled" : "disabled"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "active" : "passive"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("ellipticCurve")}
|
||||
fieldId="kc-elliptic-curve"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:ellipticCurve"
|
||||
fieldLabelId="realm-settings:ellipticCurve"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.ecdsaEllipticCurveKey"
|
||||
control={form.control}
|
||||
defaultValue={["P-256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-ecdsa-elliptic-curve"
|
||||
onToggle={(isExpanded) => setIsKeySizeDropdownOpen(isExpanded)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsKeySizeDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("ellipticCurve")}
|
||||
data-testid="select-elliptic-curve-size"
|
||||
>
|
||||
{ecdsaEllipticCurveOptions?.map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-ecdsa-form-buttons">
|
||||
<Button
|
||||
className="kc-ecdsa-form-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-ecdsa-form-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function ECDSAGeneratedSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<ECDSAGeneratedForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ECDSAGeneratedForm } from "./ECDSAGeneratedForm";
|
||||
|
||||
type ECDSAGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const ECDSAGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: ECDSAGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<ECDSAGeneratedForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,374 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type HMACGeneratedFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType?: string;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const HMACGeneratedForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
}: HMACGeneratedFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false);
|
||||
const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] =
|
||||
useState(false);
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const hmacSecretSizeOptions = allComponentTypes[2].properties[3].options;
|
||||
|
||||
const hmacAlgorithmOptions = allComponentTypes[2].properties[4].options;
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="realm-settings:providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "enabled" : "disabled"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "active" : "passive"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("secretSize")}
|
||||
fieldId="kc-hmac-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:secretSize"
|
||||
fieldLabelId="realm-settings:secretSize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.secretSize"
|
||||
control={form.control}
|
||||
defaultValue={["64"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-hmac-keysize"
|
||||
onToggle={(isExpanded) => setIsKeySizeDropdownOpen(isExpanded)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsKeySizeDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("hmacKeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{hmacSecretSizeOptions!.map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={form.control}
|
||||
defaultValue={["HS-256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={(isExpanded) =>
|
||||
setIsEllipticCurveDropdownOpen(isExpanded)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsEllipticCurveDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("emailTheme")}
|
||||
isOpen={isEllipticCurveDropdownOpen}
|
||||
placeholderText="Select one..."
|
||||
data-testid="select-email-theme"
|
||||
>
|
||||
{hmacAlgorithmOptions!.map((p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`email-theme-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-hmac-form-buttons">
|
||||
<Button
|
||||
className="kc-hmac-form-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-hmac-form-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function HMACGeneratedSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<HMACGeneratedForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HMACGeneratedForm } from "./HMACGeneratedForm";
|
||||
|
||||
type HMACGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const HMACGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: HMACGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<HMACGeneratedForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,430 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type JavaKeystoreFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType?: string;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const JavaKeystoreForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
}: JavaKeystoreFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
const [isAlgorithmDropdownOpen, setIsAlgorithmDropdownOpen] = useState(false);
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const javaKeystoreAlgorithmOptions =
|
||||
allComponentTypes[3].properties[3].options;
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="realm-settings:providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="realm-settings:enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "enabled" : "disabled"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "active" : "passive"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={form.control}
|
||||
defaultValue={["RS256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={(isExpanded) => setIsAlgorithmDropdownOpen(isExpanded)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsAlgorithmDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isAlgorithmDropdownOpen}
|
||||
placeholderText="Select one..."
|
||||
data-testid="select-algorithm"
|
||||
>
|
||||
{javaKeystoreAlgorithmOptions!.map((p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`algorithm-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystore")}
|
||||
fieldId="kc-keystore"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystore"
|
||||
fieldLabelId="realm-settings:keystore"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystore"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keystore")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystorePassword")}
|
||||
fieldId="kc-keystore-password"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystorePassword"
|
||||
fieldLabelId="realm-settings:keystorePassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystorePassword"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="select-display-name"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyAlias")}
|
||||
fieldId="kc-key-alias"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyAlias"
|
||||
fieldLabelId="realm-settings:keyAlias"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyAlias"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keyAlias")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="key-alias"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyPassword")}
|
||||
fieldId="kc-key-password"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyPassword"
|
||||
fieldLabelId="realm-settings:keyPassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyPassword"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keyPassword")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="key-password"
|
||||
></TextInput>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-java-keystore-form-buttons">
|
||||
<Button
|
||||
className="kc-java-keystore-form-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-java-keystore-form-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function JavaKeystoreSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<JavaKeystoreForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { JavaKeystoreForm } from "./JavaKeystoreForm";
|
||||
|
||||
type JavaKeystoreModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const JavaKeystoreModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: JavaKeystoreModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<JavaKeystoreForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
import React from "react";
|
||||
import { PageSection } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import {
|
||||
MatchParams,
|
||||
RSAGeneratedForm,
|
||||
} from "../rsa-generated/RSAGeneratedForm";
|
||||
|
||||
export default function RSAEncGeneratedSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<RSAGeneratedForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RSAGeneratedForm } from "../rsa-generated/RSAGeneratedForm";
|
||||
|
||||
type RSAEncGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const RSAEncGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: RSAEncGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<RSAGeneratedForm
|
||||
isRSAEncGenerated
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,392 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type RSAGeneratedFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType?: string;
|
||||
isRSAEncGenerated?: boolean;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const RSAGeneratedForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
isRSAEncGenerated,
|
||||
}: RSAGeneratedFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false);
|
||||
const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] =
|
||||
useState(false);
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { url } = useRouteMatch();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const isTypeRSAEncGenerated =
|
||||
url.includes("rsa-enc-generated") || isRSAEncGenerated;
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const rsaGeneratedKeySizeOptions =
|
||||
allComponentTypes[6].properties[3].options ?? [];
|
||||
|
||||
const rsaGeneratedAlgorithmOptions =
|
||||
allComponentTypes[6].properties[4].options ?? [];
|
||||
|
||||
const rsaEncGeneratedKeySizeOptions =
|
||||
allComponentTypes[5].properties[3].options ?? [];
|
||||
|
||||
const rsaEncGeneratedAlgorithmOptions =
|
||||
allComponentTypes[5].properties[4].options ?? [];
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="client-scopes:providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:enabled"
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "enabled" : "disabled"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "active" : "passive"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keySize")}
|
||||
fieldId="kc-rsa-generated-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keySize"
|
||||
fieldLabelId="realm-settings:keySize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keySize"
|
||||
control={form.control}
|
||||
defaultValue={isTypeRSAEncGenerated ? ["4096"] : ["2048"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-generated-keysize"
|
||||
onToggle={(isExpanded) => setIsKeySizeDropdownOpen(isExpanded)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsKeySizeDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("KeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{(isTypeRSAEncGenerated
|
||||
? rsaEncGeneratedKeySizeOptions
|
||||
: rsaGeneratedKeySizeOptions
|
||||
).map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={form.control}
|
||||
defaultValue={isTypeRSAEncGenerated ? ["RSA-OAEP"] : ["RS256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={(isExpanded) =>
|
||||
setIsEllipticCurveDropdownOpen(isExpanded)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsEllipticCurveDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("emailTheme")}
|
||||
isOpen={isEllipticCurveDropdownOpen}
|
||||
placeholderText="Select one..."
|
||||
data-testid="select-email-theme"
|
||||
>
|
||||
{(isTypeRSAEncGenerated
|
||||
? rsaEncGeneratedAlgorithmOptions
|
||||
: rsaGeneratedAlgorithmOptions
|
||||
).map((p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`email-theme-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-rsa-generated-form-buttons">
|
||||
<Button
|
||||
className="kc-rsa-generated-form-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-rsa-generated-form-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function RSAGeneratedSettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<RSAGeneratedForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RSAGeneratedForm } from "./RSAGeneratedForm";
|
||||
|
||||
type RSAGeneratedModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const RSAGeneratedModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: RSAGeneratedModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<RSAGeneratedForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,394 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FileUpload,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Switch,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import { convertToFormValues, KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
|
||||
type RSAFormProps = {
|
||||
handleModalToggle?: () => void;
|
||||
refresh?: () => void;
|
||||
editMode?: boolean;
|
||||
providerType?: string;
|
||||
};
|
||||
|
||||
export interface MatchParams {
|
||||
providerType: string;
|
||||
}
|
||||
|
||||
export const RSAForm = ({
|
||||
editMode,
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
refresh,
|
||||
}: RSAFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const serverInfo = useServerInfo();
|
||||
|
||||
const [component, setComponent] = useState<ComponentRepresentation>();
|
||||
|
||||
const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false);
|
||||
|
||||
const [keyFileName, setKeyFileName] = useState("");
|
||||
const [certificateFileName, setCertificateFileName] = useState("");
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const providerId =
|
||||
useRouteMatch<MatchParams>("/:providerType?")?.params.providerType;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
parentId: component.parentId,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { priority: ["0"] },
|
||||
});
|
||||
handleModalToggle?.();
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
refresh?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (editMode) return await adminClient.components.findOne({ id: id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
setupForm(result);
|
||||
setComponent(result);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const rsaAlgOptions = allComponentTypes[4].properties[3].options;
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
id="add-provider"
|
||||
className="pf-u-mt-lg"
|
||||
role="manage-realm"
|
||||
onSubmit={form.handleSubmit(save)}
|
||||
>
|
||||
{editMode && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="realm-settings:providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="id"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly={editMode}
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={id}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
form.errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
{!editMode && (
|
||||
<Controller
|
||||
name="name"
|
||||
control={form.control}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("consoleDisplayName")}
|
||||
defaultValue={providerType}
|
||||
value={value}
|
||||
onChange={(value) => onChange(value)}
|
||||
data-testid="display-name-input"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{editMode && (
|
||||
<TextInput
|
||||
ref={form.register()}
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
defaultValue={providerId}
|
||||
validated={
|
||||
form.errors.name
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "enabled" : "disabled"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={form.control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid={value[0] === "true" ? "active" : "passive"}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
defaultValue={["RS256"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-algorithm"
|
||||
onToggle={() => setIsRSAalgDropdownOpen(!isRSAalgDropdownOpen)}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
setIsRSAalgDropdownOpen(false);
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isRSAalgDropdownOpen}
|
||||
data-testid="select-rsa-algorithm"
|
||||
>
|
||||
{rsaAlgOptions!.map((p, idx) => (
|
||||
<SelectOption
|
||||
selected={p === value}
|
||||
key={`rsa-algorithm-${idx}`}
|
||||
value={p}
|
||||
></SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("privateRSAKey")}
|
||||
fieldId="kc-private-rsa-key"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:privateRSAKey"
|
||||
fieldLabelId="realm-settings:privateRSAKey"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.privateKey"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<FileUpload
|
||||
id="importPrivateKey"
|
||||
type="text"
|
||||
value={component?.config?.privateKey[0]}
|
||||
filenamePlaceholder="Upload a PEM file or paste key below"
|
||||
filename={keyFileName}
|
||||
onChange={(value, fileName) => {
|
||||
setKeyFileName(fileName);
|
||||
onChange([value]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("x509Certificate")}
|
||||
fieldId="kc-x509Certificate"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:x509Certificate"
|
||||
fieldLabelId="realm-settings:x509Certificate"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.certificate"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<FileUpload
|
||||
id="importCertificate"
|
||||
type="text"
|
||||
value={component?.config?.certificate[0]}
|
||||
filenamePlaceholder="Upload a PEM file or paste key below"
|
||||
filename={certificateFileName}
|
||||
onChange={(value, fileName) => {
|
||||
setCertificateFileName(fileName);
|
||||
onChange([value]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup className="kc-hmac-form-buttons">
|
||||
<Button
|
||||
className="kc-hmac-form-save-button"
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
className="kc-hmac-form-cancel-button"
|
||||
onClick={(!editMode && handleModalToggle) || undefined}
|
||||
variant="link"
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function RSASettings() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const providerId = useRouteMatch<MatchParams>(
|
||||
"/:realm/realm-settings/keys/:id?/:providerType?/settings"
|
||||
)?.params.providerType;
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={providerId} />
|
||||
<PageSection variant="light">
|
||||
<RSAForm providerType={providerId} editMode />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RSAForm } from "./RSAForm";
|
||||
|
||||
type RSAModalProps = {
|
||||
providerType: string;
|
||||
handleModalToggle: () => void;
|
||||
refresh: () => void;
|
||||
open: boolean;
|
||||
};
|
||||
|
||||
export const RSAModal = ({
|
||||
providerType,
|
||||
handleModalToggle,
|
||||
open,
|
||||
refresh,
|
||||
}: RSAModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen={open}
|
||||
onClose={handleModalToggle}
|
||||
>
|
||||
<RSAForm
|
||||
providerType={providerType}
|
||||
handleModalToggle={handleModalToggle}
|
||||
refresh={refresh}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import { useHistory, useRouteMatch } from "react-router-dom";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
|
@ -10,18 +10,21 @@ import {
|
|||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
import { cellWidth } from "@patternfly/react-table";
|
||||
import { FilterIcon } from "@patternfly/react-icons";
|
||||
|
||||
import type { KeyMetadataRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/keyMetadataRepresentation";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { emptyFormatter } from "../util";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { emptyFormatter } from "../../util";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { toKeysTab } from "../routes/KeysTab";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
import { FilterIcon } from "@patternfly/react-icons";
|
||||
import "../realm-settings-section.css";
|
||||
|
||||
const FILTER_OPTIONS = ["ACTIVE", "PASSIVE", "DISABLED"] as const;
|
||||
|
||||
type KeyData = KeyMetadataRepresentation & {
|
||||
provider?: string;
|
||||
|
@ -32,18 +35,19 @@ type KeysListTabProps = {
|
|||
};
|
||||
|
||||
export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
||||
const { t } = useTranslation("roles");
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const history = useHistory();
|
||||
const { url } = useRouteMatch();
|
||||
|
||||
const [key, setKey] = useState(0);
|
||||
const [publicKey, setPublicKey] = useState("");
|
||||
const [certificate, setCertificate] = useState("");
|
||||
const [filterDropdownOpen, setFilterDropdownOpen] = useState(false);
|
||||
const [filterType, setFilterType] = useState("Active keys");
|
||||
const [filterType, setFilterType] = useState<typeof FILTER_OPTIONS[number]>(
|
||||
FILTER_OPTIONS[0]
|
||||
);
|
||||
|
||||
const refresh = () => {
|
||||
setKey(new Date().getTime());
|
||||
setKey(key + 1);
|
||||
};
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
|
@ -55,8 +59,12 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
});
|
||||
|
||||
const keys = keysMetaData.keys;
|
||||
const filtered =
|
||||
filterType !== FILTER_OPTIONS[0]
|
||||
? keys?.filter(({ status }) => status === filterType)
|
||||
: keys;
|
||||
|
||||
return keys?.map((key) => {
|
||||
return filtered?.map((key) => {
|
||||
const provider = realmComponents.find(
|
||||
(component: ComponentRepresentation) => component.id === key.providerId
|
||||
);
|
||||
|
@ -64,56 +72,8 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
})!;
|
||||
};
|
||||
|
||||
const activeKeysLoader = async () => {
|
||||
const keysMetaData = await adminClient.realms.getKeys({
|
||||
realm: realmName,
|
||||
});
|
||||
const keys = keysMetaData.keys;
|
||||
|
||||
const activeKeysCopy = keys!.filter((i) => i.status === "ACTIVE");
|
||||
|
||||
return activeKeysCopy.map((key) => {
|
||||
const provider = realmComponents.find(
|
||||
(component: ComponentRepresentation) => component.id === key.providerId
|
||||
);
|
||||
return { ...key, provider: provider?.name } as KeyData;
|
||||
})!;
|
||||
};
|
||||
|
||||
const passiveKeysLoader = async () => {
|
||||
const keysMetaData = await adminClient.realms.getKeys({
|
||||
realm: realmName,
|
||||
});
|
||||
const keys = keysMetaData.keys;
|
||||
|
||||
const passiveKeys = keys!.filter((i) => i.status === "PASSIVE");
|
||||
|
||||
return passiveKeys.map((key) => {
|
||||
const provider = realmComponents.find(
|
||||
(component: ComponentRepresentation) => component.id === key.providerId
|
||||
);
|
||||
return { ...key, provider: provider?.name } as KeyData;
|
||||
})!;
|
||||
};
|
||||
|
||||
const disabledKeysLoader = async () => {
|
||||
const keysMetaData = await adminClient.realms.getKeys({
|
||||
realm: realmName,
|
||||
});
|
||||
const keys = keysMetaData.keys;
|
||||
|
||||
const disabledKeys = keys!.filter((i) => i.status === "DISABLED");
|
||||
|
||||
return disabledKeys.map((key) => {
|
||||
const provider = realmComponents!.find(
|
||||
(component: ComponentRepresentation) => component.id === key.providerId
|
||||
);
|
||||
return { ...key, provider: provider?.name } as KeyData;
|
||||
})!;
|
||||
};
|
||||
|
||||
const [togglePublicKeyDialog, PublicKeyDialog] = useConfirmDialog({
|
||||
titleKey: t("realm-settings:publicKeys").slice(0, -1),
|
||||
titleKey: t("publicKeys").slice(0, -1),
|
||||
messageKey: publicKey,
|
||||
continueButtonLabel: "common:close",
|
||||
continueButtonVariant: ButtonVariant.primary,
|
||||
|
@ -121,15 +81,13 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
});
|
||||
|
||||
const [toggleCertificateDialog, CertificateDialog] = useConfirmDialog({
|
||||
titleKey: t("realm-settings:certificate"),
|
||||
titleKey: t("certificate"),
|
||||
messageKey: certificate,
|
||||
continueButtonLabel: "common:close",
|
||||
continueButtonVariant: ButtonVariant.primary,
|
||||
onConfirm: () => Promise.resolve(),
|
||||
});
|
||||
|
||||
const goToCreate = () => history.push(`${url}/add-role`);
|
||||
|
||||
const ProviderRenderer = ({ provider }: KeyData) => provider;
|
||||
|
||||
const ButtonRenderer = ({ type, publicKey, certificate }: KeyData) => {
|
||||
|
@ -143,7 +101,7 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
variant="secondary"
|
||||
id="kc-public-key"
|
||||
>
|
||||
{t("realm-settings:publicKeys").slice(0, -1)}
|
||||
{t("publicKeys").slice(0, -1)}
|
||||
</Button>
|
||||
);
|
||||
} else if (type === "RSA") {
|
||||
|
@ -157,7 +115,7 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
variant="secondary"
|
||||
id="kc-rsa-public-key"
|
||||
>
|
||||
{t("realm-settings:publicKeys").slice(0, -1)}
|
||||
{t("publicKeys").slice(0, -1)}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
|
@ -167,32 +125,13 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
variant="secondary"
|
||||
id="kc-certificate"
|
||||
>
|
||||
{t("realm-settings:certificate")}
|
||||
{t("certificate")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const options = [
|
||||
<SelectOption
|
||||
key={1}
|
||||
data-testid="active-keys-option"
|
||||
value={t("realm-settings:activeKeys")}
|
||||
isPlaceholder
|
||||
/>,
|
||||
<SelectOption
|
||||
data-testid="passive-keys-option"
|
||||
key={2}
|
||||
value={t("realm-settings:passiveKeys")}
|
||||
/>,
|
||||
<SelectOption
|
||||
data-testid="disabled-keys-option"
|
||||
key={3}
|
||||
value={t("realm-settings:disabledKeys")}
|
||||
/>,
|
||||
];
|
||||
|
||||
return (
|
||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||
<PublicKeyDialog />
|
||||
|
@ -200,16 +139,8 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
<KeycloakDataTable
|
||||
isNotCompact={true}
|
||||
key={key}
|
||||
loader={
|
||||
filterType === "Active keys"
|
||||
? activeKeysLoader
|
||||
: filterType === "Passive keys"
|
||||
? passiveKeysLoader
|
||||
: filterType === "Disabled keys"
|
||||
? disabledKeysLoader
|
||||
: loader
|
||||
}
|
||||
ariaLabelKey="realm-settings:keysList"
|
||||
loader={loader}
|
||||
ariaLabelKey="keysList"
|
||||
searchPlaceholderKey="realm-settings:searchKey"
|
||||
searchTypeComponent={
|
||||
<Select
|
||||
|
@ -221,61 +152,71 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
|||
onToggle={() => setFilterDropdownOpen(!filterDropdownOpen)}
|
||||
toggleIcon={<FilterIcon />}
|
||||
onSelect={(_, value) => {
|
||||
setFilterType(value as string);
|
||||
setFilterType(
|
||||
FILTER_OPTIONS.find((o) => o === value.toString()) ||
|
||||
FILTER_OPTIONS[0]
|
||||
);
|
||||
refresh();
|
||||
setFilterDropdownOpen(false);
|
||||
}}
|
||||
selections={filterType}
|
||||
>
|
||||
{options}
|
||||
{FILTER_OPTIONS.map((option) => (
|
||||
<SelectOption
|
||||
key={option}
|
||||
data-testid={`${option}-option`}
|
||||
value={option}
|
||||
>
|
||||
{t(`keysFilter.${option}`)}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
}
|
||||
canSelectAll
|
||||
columns={[
|
||||
{
|
||||
name: "algorithm",
|
||||
displayKey: "realm-settings:algorithm",
|
||||
displayKey: "algorithm",
|
||||
cellFormatters: [emptyFormatter()],
|
||||
transforms: [cellWidth(15)],
|
||||
},
|
||||
{
|
||||
name: "type",
|
||||
displayKey: "realm-settings:type",
|
||||
displayKey: "type",
|
||||
cellFormatters: [emptyFormatter()],
|
||||
transforms: [cellWidth(10)],
|
||||
},
|
||||
{
|
||||
name: "kid",
|
||||
displayKey: "realm-settings:kid",
|
||||
displayKey: "kid",
|
||||
cellFormatters: [emptyFormatter()],
|
||||
transforms: [cellWidth(10)],
|
||||
},
|
||||
{
|
||||
name: "provider",
|
||||
displayKey: "realm-settings:provider",
|
||||
displayKey: "provider",
|
||||
cellRenderer: ProviderRenderer,
|
||||
cellFormatters: [emptyFormatter()],
|
||||
transforms: [cellWidth(10)],
|
||||
},
|
||||
{
|
||||
name: "publicKeys",
|
||||
displayKey: "realm-settings:publicKeys",
|
||||
displayKey: "publicKeys",
|
||||
cellRenderer: ButtonRenderer,
|
||||
cellFormatters: [],
|
||||
transforms: [cellWidth(20)],
|
||||
},
|
||||
]}
|
||||
isSearching={!!filterType}
|
||||
isSearching={filterType !== FILTER_OPTIONS[0]}
|
||||
emptyState={
|
||||
<ListEmptyState
|
||||
hasIcon={true}
|
||||
message={t("realm-settings:noKeys")}
|
||||
instructions={
|
||||
t(`realm-settings:noKeysDescription`) +
|
||||
`${filterType.toLocaleLowerCase()}.`
|
||||
hasIcon
|
||||
message={t("noKeys")}
|
||||
instructions={t("noKeysDescription")}
|
||||
primaryActionText={t("addProvider")}
|
||||
onPrimaryAction={() =>
|
||||
history.push(toKeysTab({ realm: realmName, tab: "providers" }))
|
||||
}
|
||||
primaryActionText={t("createRole")}
|
||||
onPrimaryAction={goToCreate}
|
||||
/>
|
||||
}
|
||||
/>
|
283
src/realm-settings/keys/KeysProvidersTab.tsx
Normal file
283
src/realm-settings/keys/KeysProvidersTab.tsx
Normal file
|
@ -0,0 +1,283 @@
|
|||
import React, { useMemo, useState, KeyboardEvent } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownToggle,
|
||||
InputGroup,
|
||||
PageSection,
|
||||
TextInput,
|
||||
Toolbar,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
} from "@patternfly/react-core";
|
||||
import { SearchIcon } from "@patternfly/react-icons";
|
||||
|
||||
import type { KeyMetadataRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/keyMetadataRepresentation";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
|
||||
import type { ProviderType } from "../routes/KeyProvider";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { Link, useRouteMatch } from "react-router-dom";
|
||||
import { KEY_PROVIDER_TYPE } from "../../util";
|
||||
import { DraggableTable } from "../../authentication/components/DraggableTable";
|
||||
import { KeyProviderModal } from "./key-providers/KeyProviderModal";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
|
||||
import "../realm-settings-section.css";
|
||||
|
||||
type ComponentData = KeyMetadataRepresentation & {
|
||||
id?: string;
|
||||
providerDescription?: string;
|
||||
name?: string;
|
||||
toggleHidden?: boolean;
|
||||
config?: any;
|
||||
parentId?: string;
|
||||
};
|
||||
|
||||
type KeysProvidersTabProps = {
|
||||
realmComponents: ComponentRepresentation[];
|
||||
refresh: () => void;
|
||||
};
|
||||
|
||||
export const KeysProvidersTab = ({
|
||||
realmComponents,
|
||||
refresh,
|
||||
}: KeysProvidersTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useRealm();
|
||||
const { url } = useRouteMatch();
|
||||
|
||||
const [searchVal, setSearchVal] = useState("");
|
||||
const [filteredComponents, setFilteredComponents] = useState<ComponentData[]>(
|
||||
[]
|
||||
);
|
||||
|
||||
const [isCreateModalOpen, handleModalToggle] = useToggle();
|
||||
const serverInfo = useServerInfo();
|
||||
const keyProviderComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
const providerTypes = keyProviderComponentTypes.map((item) => item.id);
|
||||
|
||||
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
|
||||
const [defaultConsoleDisplayName, setDefaultConsoleDisplayName] =
|
||||
useState<ProviderType>();
|
||||
|
||||
const [selectedComponent, setSelectedComponent] =
|
||||
useState<ComponentRepresentation>();
|
||||
|
||||
const components = useMemo(
|
||||
() =>
|
||||
realmComponents.map((component) => {
|
||||
const provider = keyProviderComponentTypes.find(
|
||||
(componentType: ComponentTypeRepresentation) =>
|
||||
component.providerId === componentType.id
|
||||
);
|
||||
|
||||
return {
|
||||
...component,
|
||||
providerDescription: provider?.helpText,
|
||||
};
|
||||
}),
|
||||
[realmComponents]
|
||||
);
|
||||
|
||||
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
|
||||
titleKey: "realm-settings:deleteProviderTitle",
|
||||
messageKey: t("deleteProviderConfirm", {
|
||||
provider: selectedComponent?.name,
|
||||
}),
|
||||
continueButtonLabel: "common:delete",
|
||||
continueButtonVariant: ButtonVariant.danger,
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await adminClient.components.del({
|
||||
id: selectedComponent!.id!,
|
||||
realm: realm,
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
addAlert(t("deleteProviderSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("realm-settings:deleteProviderError", error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const onSearch = () => {
|
||||
if (searchVal !== "") {
|
||||
setSearchVal(searchVal);
|
||||
const filteredComponents = components.filter(
|
||||
(component) =>
|
||||
component.name?.includes(searchVal) ||
|
||||
component.providerId?.includes(searchVal)
|
||||
);
|
||||
setFilteredComponents(filteredComponents);
|
||||
} else {
|
||||
setSearchVal("");
|
||||
setFilteredComponents(components);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
onSearch();
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (value: string) => {
|
||||
setSearchVal(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isCreateModalOpen && defaultConsoleDisplayName && (
|
||||
<KeyProviderModal
|
||||
providerType={defaultConsoleDisplayName}
|
||||
onClose={() => {
|
||||
handleModalToggle();
|
||||
refresh();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<DeleteConfirm />
|
||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||
<Toolbar>
|
||||
<ToolbarGroup className="providers-toolbar">
|
||||
<ToolbarItem>
|
||||
<InputGroup>
|
||||
<TextInput
|
||||
name={"inputGroupName"}
|
||||
id={"inputGroupName"}
|
||||
type="search"
|
||||
aria-label={t("common:search")}
|
||||
placeholder={t("common:search")}
|
||||
onChange={handleInputChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<Button
|
||||
variant={ButtonVariant.control}
|
||||
aria-label={t("common:search")}
|
||||
onClick={onSearch}
|
||||
>
|
||||
<SearchIcon />
|
||||
</Button>
|
||||
</InputGroup>
|
||||
</ToolbarItem>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
data-testid="addProviderDropdown"
|
||||
className="add-provider-dropdown"
|
||||
isOpen={providerDropdownOpen}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
onToggle={(val) => setProviderDropdownOpen(val)}
|
||||
isPrimary
|
||||
>
|
||||
{t("addProvider")}
|
||||
</DropdownToggle>
|
||||
}
|
||||
dropdownItems={[
|
||||
providerTypes.map((item) => (
|
||||
<DropdownItem
|
||||
onClick={() => {
|
||||
handleModalToggle();
|
||||
|
||||
setProviderDropdownOpen(false);
|
||||
setDefaultConsoleDisplayName(item as ProviderType);
|
||||
}}
|
||||
data-testid={`option-${item}`}
|
||||
key={item}
|
||||
>
|
||||
{item}
|
||||
</DropdownItem>
|
||||
)),
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
<DraggableTable
|
||||
variant="compact"
|
||||
keyField="id"
|
||||
data={
|
||||
filteredComponents.length === 0 ? components : filteredComponents
|
||||
}
|
||||
onDragFinish={async (_, itemOrder) => {
|
||||
const updateAll = components.map((component: ComponentData) => {
|
||||
const componentToSave = { ...component };
|
||||
delete componentToSave.providerDescription;
|
||||
|
||||
return adminClient.components.update(
|
||||
{ id: component.id! },
|
||||
{
|
||||
...componentToSave,
|
||||
config: {
|
||||
priority: [
|
||||
(
|
||||
itemOrder.length -
|
||||
itemOrder.indexOf(component.id!) +
|
||||
100
|
||||
).toString(),
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(updateAll);
|
||||
refresh();
|
||||
addAlert(t("saveProviderListSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
name: "name",
|
||||
displayKey: "realm-settings:name",
|
||||
cellRenderer: (component) => (
|
||||
<Link
|
||||
key={component.name}
|
||||
data-testid="provider-name-link"
|
||||
to={`${url}/${component.id}/${component.providerId}/settings`}
|
||||
>
|
||||
{component.name}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "providerId",
|
||||
displayKey: "realm-settings:provider",
|
||||
},
|
||||
{
|
||||
name: "providerDescription",
|
||||
displayKey: "realm-settings:providerDescription",
|
||||
},
|
||||
]}
|
||||
actions={[
|
||||
{
|
||||
title: t("common:delete"),
|
||||
onClick: (_key, _idx, component) => {
|
||||
setSelectedComponent(component as ComponentRepresentation);
|
||||
toggleDeleteDialog();
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
92
src/realm-settings/keys/KeysTab.tsx
Normal file
92
src/realm-settings/keys/KeysTab.tsx
Normal file
|
@ -0,0 +1,92 @@
|
|||
import React, { useState } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Tab, TabTitleText } from "@patternfly/react-core";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { KEY_PROVIDER_TYPE } from "../../util";
|
||||
import {
|
||||
routableTab,
|
||||
RoutableTabs,
|
||||
} from "../../components/routable-tabs/RoutableTabs";
|
||||
import { KeySubTab, toKeysTab } from "../routes/KeysTab";
|
||||
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { KeysListTab } from "./KeysListTab";
|
||||
import { KeysProvidersTab } from "./KeysProvidersTab";
|
||||
|
||||
const sortByPriority = (components: ComponentRepresentation[]) => {
|
||||
const sortedComponents = [...components].sort((a, b) => {
|
||||
const priorityA = Number(a.config?.priority);
|
||||
const priorityB = Number(b.config?.priority);
|
||||
|
||||
return (
|
||||
(!isNaN(priorityB) ? priorityB : 0) - (!isNaN(priorityA) ? priorityA : 0)
|
||||
);
|
||||
});
|
||||
|
||||
return sortedComponents;
|
||||
};
|
||||
|
||||
export const KeysTab = () => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const history = useHistory();
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
|
||||
const [realmComponents, setRealmComponents] =
|
||||
useState<ComponentRepresentation[]>();
|
||||
const [key, setKey] = useState(0);
|
||||
const refresh = () => {
|
||||
setKey(key + 1);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
() =>
|
||||
adminClient.components.find({
|
||||
type: KEY_PROVIDER_TYPE,
|
||||
realm: realmName,
|
||||
}),
|
||||
(components) => setRealmComponents(sortByPriority(components)),
|
||||
[key]
|
||||
);
|
||||
|
||||
if (!realmComponents) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
||||
const keysRoute = (tab: KeySubTab) =>
|
||||
routableTab({
|
||||
to: toKeysTab({ realm: realmName, tab }),
|
||||
history,
|
||||
});
|
||||
|
||||
return (
|
||||
<RoutableTabs
|
||||
mountOnEnter
|
||||
unmountOnExit
|
||||
defaultLocation={toKeysTab({ realm: realmName, tab: "list" })}
|
||||
>
|
||||
<Tab
|
||||
id="keysList"
|
||||
data-testid="rs-keys-list-tab"
|
||||
aria-label="keys-list-subtab"
|
||||
title={<TabTitleText>{t("keysList")}</TabTitleText>}
|
||||
{...keysRoute("list")}
|
||||
>
|
||||
<KeysListTab realmComponents={realmComponents} />
|
||||
</Tab>
|
||||
<Tab
|
||||
id="providers"
|
||||
data-testid="rs-providers-tab"
|
||||
aria-label="rs-providers-tab"
|
||||
title={<TabTitleText>{t("providers")}</TabTitleText>}
|
||||
{...keysRoute("providers")}
|
||||
>
|
||||
<KeysProvidersTab realmComponents={realmComponents} refresh={refresh} />
|
||||
</Tab>
|
||||
</RoutableTabs>
|
||||
);
|
||||
};
|
257
src/realm-settings/keys/key-providers/KeyProviderForm.tsx
Normal file
257
src/realm-settings/keys/key-providers/KeyProviderForm.tsx
Normal file
|
@ -0,0 +1,257 @@
|
|||
import React from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
AlertVariant,
|
||||
FormGroup,
|
||||
ValidatedOptions,
|
||||
Switch,
|
||||
TextInput,
|
||||
PageSection,
|
||||
ActionGroup,
|
||||
Button,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type { KeyProviderParams, ProviderType } from "../../routes/KeyProvider";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../util";
|
||||
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||
import AesView from "./aes-generated/View";
|
||||
import EcdsaView from "./ecdsa-generated/View";
|
||||
import HmacView from "./hmac-generated/View";
|
||||
import JavaKeystoreView from "./java-keystore/View";
|
||||
import RsaView from "./rsa/View";
|
||||
import RsaGeneratedView from "./rsa-generated/View";
|
||||
|
||||
type KeyProviderFormProps = {
|
||||
id?: string;
|
||||
providerType: ProviderType;
|
||||
onClose?: () => void;
|
||||
};
|
||||
|
||||
const SubView = ({ providerType }: { providerType: ProviderType }) => {
|
||||
switch (providerType) {
|
||||
case "aes-generated":
|
||||
return <AesView />;
|
||||
case "ecdsa-generated":
|
||||
return <EcdsaView />;
|
||||
case "hmac-generated":
|
||||
return <HmacView />;
|
||||
case "java-keystore":
|
||||
return <JavaKeystoreView />;
|
||||
case "rsa":
|
||||
return <RsaView />;
|
||||
case "rsa-enc-generated":
|
||||
return <RsaGeneratedView isEnc />;
|
||||
case "rsa-generated":
|
||||
return <RsaGeneratedView />;
|
||||
|
||||
default:
|
||||
return <>invalid view type</>;
|
||||
}
|
||||
};
|
||||
|
||||
export const KeyProviderForm = ({
|
||||
providerType,
|
||||
onClose,
|
||||
}: KeyProviderFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const form = useForm<ComponentRepresentation>({
|
||||
shouldUnregister: false,
|
||||
mode: "onChange",
|
||||
});
|
||||
const { register, control, handleSubmit, errors, reset } = form;
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
if (id) {
|
||||
await adminClient.components.update(
|
||||
{ id },
|
||||
{
|
||||
...component,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
}
|
||||
);
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
} else {
|
||||
await adminClient.components.create({
|
||||
...component,
|
||||
providerId: providerType,
|
||||
providerType: KEY_PROVIDER_TYPE,
|
||||
config: { ...component.config, priority: ["0"] },
|
||||
});
|
||||
addAlert(t("saveProviderSuccess"), AlertVariant.success);
|
||||
onClose?.();
|
||||
}
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveProviderError", error);
|
||||
}
|
||||
};
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
if (id) return await adminClient.components.findOne({ id });
|
||||
},
|
||||
(result) => {
|
||||
if (result) {
|
||||
reset({ ...result });
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<FormAccess isHorizontal role="manage-realm" onSubmit={handleSubmit(save)}>
|
||||
{id && (
|
||||
<FormGroup
|
||||
label={t("providerId")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="providerId"
|
||||
/>
|
||||
}
|
||||
fieldId="providerId"
|
||||
isRequired
|
||||
>
|
||||
<TextInput
|
||||
ref={register}
|
||||
id="id"
|
||||
type="text"
|
||||
name="id"
|
||||
isReadOnly
|
||||
aria-label={t("providerId")}
|
||||
data-testid="providerId-input"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("common:name")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="client-scopes-help:mapperName"
|
||||
fieldLabelId="name"
|
||||
/>
|
||||
}
|
||||
fieldId="name"
|
||||
isRequired
|
||||
validated={
|
||||
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
rules={{ required: true }}
|
||||
defaultValue={providerType}
|
||||
render={({ onChange, value }) => (
|
||||
<TextInput
|
||||
id="name"
|
||||
type="text"
|
||||
aria-label={t("common:name")}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
data-testid="name-input"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="kc-enabled"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("realm-settings-help:enabled")}
|
||||
fieldLabelId="enabled"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.enabled"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-enabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid="enabled"
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("active")}
|
||||
fieldId="kc-active"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:active"
|
||||
fieldLabelId="realm-settings:active"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.active"
|
||||
control={control}
|
||||
defaultValue={["true"]}
|
||||
render={({ onChange, value }) => {
|
||||
return (
|
||||
<Switch
|
||||
id="kc-active"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value[0] === "true"}
|
||||
data-testid="active"
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormProvider {...form}>
|
||||
<SubView providerType={providerType} />
|
||||
</FormProvider>
|
||||
<ActionGroup>
|
||||
<Button
|
||||
data-testid="add-provider-button"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button onClick={() => onClose?.()} variant="link">
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
);
|
||||
};
|
||||
|
||||
export default function KeyProviderFormPage() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const params = useParams<KeyProviderParams>();
|
||||
return (
|
||||
<>
|
||||
<ViewHeader titleKey={t("editProvider")} subKey={params.providerType} />
|
||||
<PageSection variant="light">
|
||||
<KeyProviderForm {...params} />
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
}
|
28
src/realm-settings/keys/key-providers/KeyProviderModal.tsx
Normal file
28
src/realm-settings/keys/key-providers/KeyProviderModal.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import React from "react";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { KeyProviderForm } from "./KeyProviderForm";
|
||||
import type { ProviderType } from "../../routes/KeyProvider";
|
||||
|
||||
type KeyProviderModalProps = {
|
||||
providerType: ProviderType;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export const KeyProviderModal = ({
|
||||
providerType,
|
||||
onClose,
|
||||
}: KeyProviderModalProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
return (
|
||||
<Modal
|
||||
className="add-provider-modal"
|
||||
variant={ModalVariant.medium}
|
||||
title={t("addProvider")}
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
>
|
||||
<KeyProviderForm providerType={providerType} onClose={onClose} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
64
src/realm-settings/keys/key-providers/aes-generated/View.tsx
Normal file
64
src/realm-settings/keys/key-providers/aes-generated/View.tsx
Normal file
|
@ -0,0 +1,64 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
|
||||
const [isKeySizeDropdownOpen, toggleDropdown] = useToggle();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
const aesSecretSizeOptions = allComponentTypes[0].properties[3].options ?? [];
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
label={t("AESKeySize")}
|
||||
fieldId="kc-aes-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:AESKeySize"
|
||||
fieldLabelId="realm-settings:AESKeySize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.secretSize"
|
||||
control={control}
|
||||
defaultValue={[aesSecretSizeOptions[0]]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-aes-keysize"
|
||||
onToggle={toggleDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("aesKeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{aesSecretSizeOptions.map((item) => (
|
||||
<SelectOption selected={item === value} key={item} value={item} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
const [isKeySizeDropdownOpen, toggleDropdown] = useToggle();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const ecdsaEllipticCurveOptions = allComponentTypes[1].properties[3].options!;
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
label={t("ellipticCurve")}
|
||||
fieldId="kc-elliptic-curve"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:ellipticCurve"
|
||||
fieldLabelId="realm-settings:ellipticCurve"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.ecdsaEllipticCurveKey"
|
||||
control={control}
|
||||
defaultValue={[ecdsaEllipticCurveOptions[0]]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-ecdsa-elliptic-curve"
|
||||
onToggle={toggleDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("ellipticCurve")}
|
||||
data-testid="select-elliptic-curve-size"
|
||||
>
|
||||
{ecdsaEllipticCurveOptions.map((item) => (
|
||||
<SelectOption selected={item === value} key={item} value={item} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
109
src/realm-settings/keys/key-providers/hmac-generated/View.tsx
Normal file
109
src/realm-settings/keys/key-providers/hmac-generated/View.tsx
Normal file
|
@ -0,0 +1,109 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
|
||||
const [isKeySizeDropdownOpen, toggleKeySizeDropdown] = useToggle();
|
||||
const [isEllipticCurveDropdownOpen, toggleEllipticDropdown] = useToggle();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const hmacSecretSizeOptions =
|
||||
allComponentTypes[2].properties[3].options ?? [];
|
||||
|
||||
const hmacAlgorithmOptions = allComponentTypes[2].properties[4].options ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("secretSize")}
|
||||
fieldId="kc-hmac-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:secretSize"
|
||||
fieldLabelId="realm-settings:secretSize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.secretSize"
|
||||
control={control}
|
||||
defaultValue={[hmacSecretSizeOptions[3]]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-hmac-keysize"
|
||||
onToggle={toggleKeySizeDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleKeySizeDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("hmacKeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{hmacSecretSizeOptions.map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={control}
|
||||
defaultValue={[hmacAlgorithmOptions[0]]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={toggleEllipticDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleEllipticDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("emailTheme")}
|
||||
isOpen={isEllipticCurveDropdownOpen}
|
||||
>
|
||||
{hmacAlgorithmOptions!.map((p, idx) => (
|
||||
<SelectOption selected={p === value} key={idx} value={p} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
);
|
||||
}
|
167
src/realm-settings/keys/key-providers/java-keystore/View.tsx
Normal file
167
src/realm-settings/keys/key-providers/java-keystore/View.tsx
Normal file
|
@ -0,0 +1,167 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
const [isAlgorithmDropdownOpen, toggleDropdown] = useToggle();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const javaKeystoreAlgorithmOptions =
|
||||
allComponentTypes[3].properties[3].options ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={control}
|
||||
defaultValue={[javaKeystoreAlgorithmOptions[0]]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={toggleDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isAlgorithmDropdownOpen}
|
||||
>
|
||||
{javaKeystoreAlgorithmOptions!.map((p, idx) => (
|
||||
<SelectOption selected={p === value} key={idx} value={p} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystore")}
|
||||
fieldId="kc-keystore"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystore"
|
||||
fieldLabelId="realm-settings:keystore"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystore"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keystore")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="keystore"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keystorePassword")}
|
||||
fieldId="kc-keystore-password"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keystorePassword"
|
||||
fieldLabelId="realm-settings:keystorePassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keystorePassword"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("consoleDisplayName")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="keystorePassword"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyAlias")}
|
||||
fieldId="kc-key-alias"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyAlias"
|
||||
fieldLabelId="realm-settings:keyAlias"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyAlias"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keyAlias")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="key-alias"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("keyPassword")}
|
||||
fieldId="kc-key-password"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keyPassword"
|
||||
fieldLabelId="realm-settings:keyPassword"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keyPassword"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange }) => (
|
||||
<TextInput
|
||||
aria-label={t("keyPassword")}
|
||||
onChange={(value) => {
|
||||
onChange([value.toString()]);
|
||||
}}
|
||||
data-testid="key-password"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
);
|
||||
}
|
123
src/realm-settings/keys/key-providers/rsa-generated/View.tsx
Normal file
123
src/realm-settings/keys/key-providers/rsa-generated/View.tsx
Normal file
|
@ -0,0 +1,123 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View({ isEnc = false }: { isEnc?: boolean }) {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
|
||||
const [isKeySizeDropdownOpen, toggleKeySizeDropdown] = useToggle();
|
||||
const [isEllipticCurveDropdownOpen, toggleEllipticCurveDropdown] =
|
||||
useToggle();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const rsaGeneratedKeySizeOptions =
|
||||
allComponentTypes[6].properties[3].options ?? [];
|
||||
|
||||
const rsaGeneratedAlgorithmOptions =
|
||||
allComponentTypes[6].properties[4].options ?? [];
|
||||
|
||||
const rsaEncGeneratedKeySizeOptions =
|
||||
allComponentTypes[5].properties[3].options ?? [];
|
||||
|
||||
const rsaEncGeneratedAlgorithmOptions =
|
||||
allComponentTypes[5].properties[4].options ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("keySize")}
|
||||
fieldId="kc-rsa-generated-keysize"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:keySize"
|
||||
fieldLabelId="realm-settings:keySize"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.keySize"
|
||||
control={control}
|
||||
defaultValue={isEnc ? ["4096"] : ["2048"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-generated-keysize"
|
||||
onToggle={toggleKeySizeDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleKeySizeDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
isOpen={isKeySizeDropdownOpen}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("KeySize")}
|
||||
data-testid="select-secret-size"
|
||||
>
|
||||
{(isEnc
|
||||
? rsaEncGeneratedKeySizeOptions
|
||||
: rsaGeneratedKeySizeOptions
|
||||
).map((item) => (
|
||||
<SelectOption
|
||||
selected={item === value}
|
||||
key={item}
|
||||
value={item}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
control={control}
|
||||
defaultValue={isEnc ? ["RSA-OAEP"] : ["RS256"]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-elliptic"
|
||||
onToggle={toggleEllipticCurveDropdown}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleEllipticCurveDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isEllipticCurveDropdownOpen}
|
||||
>
|
||||
{(isEnc
|
||||
? rsaEncGeneratedAlgorithmOptions
|
||||
: rsaGeneratedAlgorithmOptions
|
||||
).map((p, idx) => (
|
||||
<SelectOption selected={p === value} key={idx} value={p} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
);
|
||||
}
|
127
src/realm-settings/keys/key-providers/rsa/View.tsx
Normal file
127
src/realm-settings/keys/key-providers/rsa/View.tsx
Normal file
|
@ -0,0 +1,127 @@
|
|||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext, Controller } from "react-hook-form";
|
||||
import {
|
||||
FileUpload,
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { useServerInfo } from "../../../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||
import { KEY_PROVIDER_TYPE } from "../../../../util";
|
||||
import useToggle from "../../../../utils/useToggle";
|
||||
|
||||
export default function View() {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const { control } = useFormContext();
|
||||
const [isRSAalgDropdownOpen, toggleDropdown] = useToggle();
|
||||
const [privateKey, setPrivateKey] = useState("");
|
||||
const [certificate, setCertificate] = useState("");
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const allComponentTypes =
|
||||
serverInfo.componentTypes?.[KEY_PROVIDER_TYPE] ?? [];
|
||||
|
||||
const rsaAlgOptions = allComponentTypes[4].properties[3].options ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("algorithm")}
|
||||
fieldId="kc-algorithm"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:algorithm"
|
||||
fieldLabelId="realm-settings:algorithm"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.algorithm"
|
||||
defaultValue={[rsaAlgOptions[0]]}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-rsa-algorithm"
|
||||
onToggle={() => toggleDropdown()}
|
||||
onSelect={(_, value) => {
|
||||
onChange([value.toString()]);
|
||||
toggleDropdown();
|
||||
}}
|
||||
selections={[value.toString()]}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("algorithm")}
|
||||
isOpen={isRSAalgDropdownOpen}
|
||||
data-testid="select-rsa-algorithm"
|
||||
>
|
||||
{rsaAlgOptions!.map((p, idx) => (
|
||||
<SelectOption selected={p === value} key={idx} value={p} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("privateRSAKey")}
|
||||
fieldId="kc-private-rsa-key"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:privateRSAKey"
|
||||
fieldLabelId="realm-settings:privateRSAKey"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.privateKey"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<FileUpload
|
||||
id="importPrivateKey"
|
||||
type="text"
|
||||
value={value.value}
|
||||
filename={privateKey}
|
||||
onChange={(value, filename) => {
|
||||
onChange(value);
|
||||
setPrivateKey(filename);
|
||||
}}
|
||||
filenamePlaceholder={t("filenamePlaceholder")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("x509Certificate")}
|
||||
fieldId="kc-x509Certificate"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:x509Certificate"
|
||||
fieldLabelId="realm-settings:x509Certificate"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="config.certificate"
|
||||
control={control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<FileUpload
|
||||
id="importCertificate"
|
||||
type="text"
|
||||
value={value}
|
||||
filename={certificate}
|
||||
onChange={(value, filename) => {
|
||||
onChange(value);
|
||||
setCertificate(filename);
|
||||
}}
|
||||
filenamePlaceholder={t("filenamePlaceholder")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -10,7 +10,7 @@ export default {
|
|||
"If you delete this realm, all associated data will be removed.",
|
||||
deleteProviderTitle: "Delete key provider?",
|
||||
deleteProviderConfirm:
|
||||
"Are you sure you want to permanently delete the key provider ",
|
||||
"Are you sure you want to permanently delete the key provider {{provider}}?",
|
||||
deleteProviderSuccess: "Success. The provider has been deleted.",
|
||||
deleteProviderError: "Error deleting the provider",
|
||||
deletedSuccess: "The realm has been deleted",
|
||||
|
@ -84,6 +84,7 @@ export default {
|
|||
AESKeySize: "AES Key Size",
|
||||
active: "Active",
|
||||
privateRSAKey: "Private RSA Key",
|
||||
filenamePlaceholder: "Upload a PEM file or paste key below",
|
||||
x509Certificate: "X509 Certificate",
|
||||
ellipticCurve: "Elliptic Curve",
|
||||
secretSize: "Secret size",
|
||||
|
@ -96,11 +97,13 @@ export default {
|
|||
providerDescription: "Provider description",
|
||||
addProvider: "Add provider",
|
||||
publicKeys: "Public keys",
|
||||
activeKeys: "Active keys",
|
||||
passiveKeys: "Passive keys",
|
||||
disabledKeys: "Disabled keys",
|
||||
keysFilter: {
|
||||
ACTIVE: "Active keys",
|
||||
PASSIVE: "Passive keys",
|
||||
DISABLED: "Disabled keys",
|
||||
},
|
||||
noKeys: "No keys",
|
||||
noKeysDescription: "You haven't created any ",
|
||||
noKeysDescription: "You haven't created any active keys",
|
||||
certificate: "Certificate",
|
||||
loginScreenCustomization: "Login screen customization",
|
||||
userRegistration: "User registration",
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import type { RouteDef } from "../route-config";
|
||||
import { AesGeneratedSettingsRoute } from "./routes/AesGeneratedSettings";
|
||||
import { EcdsaGeneratedSettingsRoute } from "./routes/EcdsaGeneratedSettings";
|
||||
import { HmacGeneratedSettingsRoute } from "./routes/HmacGeneratedSettings";
|
||||
import { JavaKeystoreSettingsRoute } from "./routes/JavaKeystoreSettings";
|
||||
import { KeyProviderFormRoute } from "./routes/KeyProvider";
|
||||
import { RealmSettingsRoute } from "./routes/RealmSettings";
|
||||
import { RsaGeneratedSettingsRoute } from "./routes/RsaGeneratedSettings";
|
||||
import { RsaSettingsRoute } from "./routes/RsaSettings";
|
||||
import { ClientPoliciesRoute } from "./routes/ClientPolicies";
|
||||
import { AddClientProfileRoute } from "./routes/AddClientProfile";
|
||||
import { ClientProfileRoute } from "./routes/ClientProfile";
|
||||
|
@ -18,18 +13,11 @@ import { EditClientPolicyConditionRoute } from "./routes/EditCondition";
|
|||
import { UserProfileRoute } from "./routes/UserProfile";
|
||||
import { AddAttributeRoute } from "./routes/AddAttribute";
|
||||
import { KeysRoute } from "./routes/KeysTab";
|
||||
import { RsaEncGeneratedSettingsRoute } from "./routes/RsaEncGeneratedSettings";
|
||||
|
||||
const routes: RouteDef[] = [
|
||||
RealmSettingsRoute,
|
||||
KeysRoute,
|
||||
AesGeneratedSettingsRoute,
|
||||
EcdsaGeneratedSettingsRoute,
|
||||
HmacGeneratedSettingsRoute,
|
||||
JavaKeystoreSettingsRoute,
|
||||
RsaEncGeneratedSettingsRoute,
|
||||
RsaGeneratedSettingsRoute,
|
||||
RsaSettingsRoute,
|
||||
KeyProviderFormRoute,
|
||||
ClientPoliciesRoute,
|
||||
AddClientProfileRoute,
|
||||
AddExecutorRoute,
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type KeyProviderParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const AesGeneratedSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/aes-generated/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/aes-generated/AESGeneratedForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toAesGeneratedSettings = (
|
||||
params: KeyProviderParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(AesGeneratedSettingsRoute.path, params),
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type EcdsaGeneratedSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const EcdsaGeneratedSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/ecdsa-generated/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/ecdsa-generated/ECDSAGeneratedForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toEcdsaGeneratedSettings = (
|
||||
params: EcdsaGeneratedSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(EcdsaGeneratedSettingsRoute.path, params),
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type HmacGeneratedSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const HmacGeneratedSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/hmac-generated/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/hmac-generated/HMACGeneratedForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toHmacGeneratedSettings = (
|
||||
params: HmacGeneratedSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(HmacGeneratedSettingsRoute.path, params),
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type JavaKeystoreSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const JavaKeystoreSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/java-keystore/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/java-keystore/JavaKeystoreForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toJavaKeystoreSettings = (
|
||||
params: JavaKeystoreSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(JavaKeystoreSettingsRoute.path, params),
|
||||
});
|
32
src/realm-settings/routes/KeyProvider.ts
Normal file
32
src/realm-settings/routes/KeyProvider.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type ProviderType =
|
||||
| "aes-generated"
|
||||
| "ecdsa-generated"
|
||||
| "hmac-generated"
|
||||
| "java-keystore"
|
||||
| "rsa"
|
||||
| "rsa-enc-generated"
|
||||
| "rsa-generated";
|
||||
|
||||
export type KeyProviderParams = {
|
||||
id: string;
|
||||
providerType: ProviderType;
|
||||
realm: string;
|
||||
};
|
||||
|
||||
export const KeyProviderFormRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/:providerType/settings",
|
||||
component: lazy(() => import("../keys/key-providers/KeyProviderForm")),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toKeyProvider = (
|
||||
params: KeyProviderParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(KeyProviderFormRoute.path, params),
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type RsaGeneratedSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const RsaEncGeneratedSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/rsa-enc-generated/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/rsa-generated/RSAGeneratedForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toRsaEncGeneratedSettings = (
|
||||
params: RsaGeneratedSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(RsaEncGeneratedSettingsRoute.path, params),
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type RsaGeneratedSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const RsaGeneratedSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/rsa-generated/settings",
|
||||
component: lazy(
|
||||
() => import("../key-providers/rsa-generated/RSAGeneratedForm")
|
||||
),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toRsaGeneratedSettings = (
|
||||
params: RsaGeneratedSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(RsaGeneratedSettingsRoute.path, params),
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
import type { LocationDescriptorObject } from "history";
|
||||
import { lazy } from "react";
|
||||
import { generatePath } from "react-router-dom";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type RsaSettingsParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const RsaSettingsRoute: RouteDef = {
|
||||
path: "/:realm/realm-settings/keys/providers/:id/rsa/settings",
|
||||
component: lazy(() => import("../key-providers/rsa/RSAForm")),
|
||||
breadcrumb: (t) => t("realm-settings:editProvider"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const toRsaSettings = (
|
||||
params: RsaSettingsParams
|
||||
): LocationDescriptorObject => ({
|
||||
pathname: generatePath(RsaSettingsRoute.path, params),
|
||||
});
|
Loading…
Reference in a new issue