Work around object collisions in forms (#3035)
This commit is contained in:
parent
cfe9706baf
commit
09d7194f9b
31 changed files with 267 additions and 141 deletions
|
@ -17,13 +17,13 @@ import { CogIcon, TrashIcon } from "@patternfly/react-icons";
|
|||
|
||||
import type AuthenticatorConfigRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||
import type AuthenticatorConfigInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigInfoRepresentation";
|
||||
import type { ConfigPropertyRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigInfoRepresentation";
|
||||
import type { ExpandableExecution } from "../execution-model";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
|
||||
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { convertToFormValues } from "../../util";
|
||||
|
||||
type ExecutionConfigModalForm = {
|
||||
alias: string;
|
||||
|
@ -54,22 +54,8 @@ export const ExecutionConfigModal = ({
|
|||
formState: { errors },
|
||||
} = form;
|
||||
|
||||
const setupForm = (
|
||||
configDescription: AuthenticatorConfigInfoRepresentation,
|
||||
config?: AuthenticatorConfigRepresentation
|
||||
) => {
|
||||
configDescription.properties!.map(
|
||||
(property: ConfigPropertyRepresentation) => {
|
||||
setValue(
|
||||
`config.${property.name}`,
|
||||
config?.config?.[property.name!] || property.defaultValue || ""
|
||||
);
|
||||
}
|
||||
);
|
||||
if (config) {
|
||||
setValue("alias", config.alias);
|
||||
setValue("id", config.id);
|
||||
}
|
||||
const setupForm = (config?: AuthenticatorConfigRepresentation) => {
|
||||
convertToFormValues(config, setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
@ -94,7 +80,7 @@ export const ExecutionConfigModal = ({
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (configDescription) setupForm(configDescription, config);
|
||||
if (configDescription) setupForm(config);
|
||||
}, [show]);
|
||||
|
||||
const save = async (changedConfig: ExecutionConfigModalForm) => {
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
} from "../../components/client-scope/ClientScopeTypes";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useLoginProviders } from "../../context/server-info/ServerInfoProvider";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import { convertAttributeNameToForm, convertToFormValues } from "../../util";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { getProtocolName } from "../../clients/utils";
|
||||
import { toClientScopes } from "../routes/ClientScopes";
|
||||
|
@ -211,7 +211,9 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="kc-display.on.consent.screen"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.display.on.consent.screen"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.display.on.consent.screen"
|
||||
)}
|
||||
control={control}
|
||||
defaultValue={displayOnConsentScreen}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -240,7 +242,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
ref={register}
|
||||
type="text"
|
||||
id="kc-consent-screen-text"
|
||||
name="attributes.consent.screen.text"
|
||||
name={convertAttributeNameToForm("attributes.consent.screen.text")}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
|
@ -256,7 +258,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="includeInTokenScope"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.include.in.token.scope"
|
||||
name={convertAttributeNameToForm("attributes.include.in.token.scope")}
|
||||
control={control}
|
||||
defaultValue="true"
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -281,7 +283,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="kc-gui-order"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.gui.order"
|
||||
name={convertAttributeNameToForm("attributes.gui.order")}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -36,6 +36,7 @@ import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
|||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { RolesList } from "../realm-roles/RolesList";
|
||||
import {
|
||||
convertAttributeNameToForm,
|
||||
convertFormValuesToObject,
|
||||
convertToFormValues,
|
||||
exportClient,
|
||||
|
@ -237,12 +238,12 @@ export default function ClientDetails() {
|
|||
form.reset({ ...client });
|
||||
convertToFormValues(client, form.setValue);
|
||||
form.setValue(
|
||||
"attributes.request.uris",
|
||||
convertAttributeNameToForm("attributes.request.uris"),
|
||||
stringToMultiline(client.attributes?.["request.uris"])
|
||||
);
|
||||
if (client.attributes?.["acr.loa.map"]) {
|
||||
form.setValue(
|
||||
"attributes.acr.loa.map",
|
||||
convertAttributeNameToForm("attributes.acr.loa.map"),
|
||||
Object.entries(JSON.parse(client.attributes["acr.loa.map"])).flatMap(
|
||||
([key, value]) => ({ key, value })
|
||||
)
|
||||
|
@ -250,21 +251,16 @@ export default function ClientDetails() {
|
|||
}
|
||||
if (client.attributes?.["default.acr.values"]) {
|
||||
form.setValue(
|
||||
"attributes.default.acr.values",
|
||||
convertAttributeNameToForm("attributes.default.acr.values"),
|
||||
stringToMultiline(client.attributes["default.acr.values"])
|
||||
);
|
||||
}
|
||||
if (client.attributes?.["post.logout.redirect.uris"]) {
|
||||
form.setValue(
|
||||
"attributes.post.logout.redirect.uris",
|
||||
convertAttributeNameToForm("attributes.post.logout.redirect.uris"),
|
||||
stringToMultiline(client.attributes["post.logout.redirect.uris"])
|
||||
);
|
||||
}
|
||||
Object.entries(client.attributes || {})
|
||||
.filter(([key]) => key.startsWith("saml.server.signature"))
|
||||
.map(([key, value]) =>
|
||||
form.setValue("attributes." + key.replaceAll(".", "$"), value)
|
||||
);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
@ -295,36 +291,29 @@ export default function ClientDetails() {
|
|||
return;
|
||||
}
|
||||
|
||||
const values = form.getValues();
|
||||
const values = convertFormValuesToObject(form.getValues());
|
||||
|
||||
if (values.attributes?.request.uris) {
|
||||
if (values.attributes?.["request.uris"]) {
|
||||
values.attributes["request.uris"] = toStringValue(
|
||||
values.attributes.request.uris
|
||||
values.attributes["request.uris"]
|
||||
);
|
||||
}
|
||||
|
||||
if (values.attributes?.default?.acr?.values) {
|
||||
if (values.attributes?.["default.acr.values"]) {
|
||||
values.attributes["default.acr.values"] = toStringValue(
|
||||
values.attributes.default.acr.values
|
||||
values.attributes["default.acr.values"]
|
||||
);
|
||||
}
|
||||
|
||||
if (values.attributes?.post.logout.redirect.uris) {
|
||||
if (values.attributes?.["post.logout.redirect.uris"]) {
|
||||
values.attributes["post.logout.redirect.uris"] = toStringValue(
|
||||
values.attributes.post.logout.redirect.uris
|
||||
values.attributes["post.logout.redirect.uris"]
|
||||
);
|
||||
}
|
||||
|
||||
const submittedClient =
|
||||
convertFormValuesToObject<ClientRepresentation>(values);
|
||||
|
||||
Object.entries(values.attributes || {})
|
||||
.filter(([key]) => key.includes("$"))
|
||||
.map(
|
||||
([key, value]) =>
|
||||
(submittedClient.attributes![key.replaceAll("$", ".")] = value)
|
||||
);
|
||||
|
||||
if (submittedClient.attributes?.["acr.loa.map"]) {
|
||||
submittedClient.attributes["acr.loa.map"] = JSON.stringify(
|
||||
Object.fromEntries(
|
||||
|
|
|
@ -12,6 +12,7 @@ import { SaveReset } from "../advanced/SaveReset";
|
|||
import environment from "../../environment";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { useAccess } from "../../context/access/Access";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
export const AccessSettings = ({
|
||||
client,
|
||||
|
@ -99,7 +100,9 @@ export const AccessSettings = ({
|
|||
}
|
||||
>
|
||||
<MultiLineInput
|
||||
name="attributes.post.logout.redirect.uris"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.post.logout.redirect.uris"
|
||||
)}
|
||||
aria-label={t("validPostLogoutRedirectUri")}
|
||||
addButtonLabel="clients:addPostLogoutRedirectUri"
|
||||
/>
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
import "./capability-config.css";
|
||||
|
||||
|
@ -68,7 +69,12 @@ export const CapabilityConfig = ({
|
|||
if (!value) {
|
||||
setValue("authorizationServicesEnabled", false);
|
||||
setValue("serviceAccountsEnabled", false);
|
||||
setValue("attributes.oidc.ciba.grant.enabled", false);
|
||||
setValue(
|
||||
convertAttributeNameToForm(
|
||||
"attributes.oidc.ciba.grant.enabled"
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -216,7 +222,9 @@ export const CapabilityConfig = ({
|
|||
</GridItem>
|
||||
<GridItem lg={8} sm={6}>
|
||||
<Controller
|
||||
name="attributes.oauth2.device.authorization.grant.enabled"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.oauth2.device.authorization.grant.enabled"
|
||||
)}
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -239,7 +247,9 @@ export const CapabilityConfig = ({
|
|||
</GridItem>
|
||||
<GridItem lg={8} sm={6}>
|
||||
<Controller
|
||||
name="attributes.oidc.ciba.grant.enabled"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.oidc.ciba.grant.enabled"
|
||||
)}
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -279,7 +289,7 @@ export const CapabilityConfig = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml.encrypt"
|
||||
name={convertAttributeNameToForm("attributes.saml.encrypt")}
|
||||
control={control}
|
||||
defaultValue={false}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -306,7 +316,9 @@ export const CapabilityConfig = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml.client.signature"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.client.signature"
|
||||
)}
|
||||
control={control}
|
||||
defaultValue={false}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -14,6 +14,7 @@ import { FormAccess } from "../../components/form-access/FormAccess";
|
|||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { KeycloakTextArea } from "../../components/keycloak-text-area/KeycloakTextArea";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
export const LoginSettingsPanel = ({ access }: { access?: boolean }) => {
|
||||
const { t } = useTranslation("clients");
|
||||
|
@ -109,7 +110,9 @@ export const LoginSettingsPanel = ({ access }: { access?: boolean }) => {
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.display.on.consent.screen"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.display.on.consent.screen"
|
||||
)}
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -136,7 +139,7 @@ export const LoginSettingsPanel = ({ access }: { access?: boolean }) => {
|
|||
>
|
||||
<KeycloakTextArea
|
||||
id="kc-consent-screen-text"
|
||||
name="attributes.consent.screen.text"
|
||||
name={convertAttributeNameToForm("attributes.consent.screen.text")}
|
||||
ref={register}
|
||||
isDisabled={!(consentRequired && displayOnConsentScreen === "true")}
|
||||
/>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { HelpItem } from "../../components/help-enabler/HelpItem";
|
|||
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { useAccess } from "../../context/access/Access";
|
||||
import { SaveReset } from "../advanced/SaveReset";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
export const LogoutPanel = ({
|
||||
save,
|
||||
|
@ -84,7 +85,9 @@ export const LogoutPanel = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="frontchannelLogoutUrl"
|
||||
name="attributes.frontchannel.logout.url"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.frontchannel.logout.url"
|
||||
)}
|
||||
ref={register({
|
||||
validate: (uri) =>
|
||||
((uri.startsWith("https://") || uri.startsWith("http://")) &&
|
||||
|
@ -123,7 +126,9 @@ export const LogoutPanel = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="backchannelLogoutUrl"
|
||||
name="attributes.backchannel.logout.url"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.backchannel.logout.url"
|
||||
)}
|
||||
ref={register({
|
||||
validate: (uri) =>
|
||||
((uri.startsWith("https://") || uri.startsWith("http://")) &&
|
||||
|
@ -150,7 +155,9 @@ export const LogoutPanel = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.backchannel.logout.session.required"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.backchannel.logout.session.required"
|
||||
)}
|
||||
defaultValue="true"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -176,7 +183,9 @@ export const LogoutPanel = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.backchannel.logout.revoke.offline.tokens"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.backchannel.logout.revoke.offline.tokens"
|
||||
)}
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
export const Toggle = ({ name, label }: { name: string; label: string }) => {
|
||||
const { t } = useTranslation("clients");
|
||||
|
@ -98,27 +99,33 @@ export const SamlConfig = () => {
|
|||
/>
|
||||
</FormGroup>
|
||||
<Toggle
|
||||
name="attributes.saml.force.name.id.format"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.force.name.id.format"
|
||||
)}
|
||||
label="forceNameIdFormat"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml.force.post.binding"
|
||||
name={convertAttributeNameToForm("attributes.saml.force.post.binding")}
|
||||
label="forcePostBinding"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml.artifact.binding"
|
||||
name={convertAttributeNameToForm("attributes.saml.artifact.binding")}
|
||||
label="forceArtifactBinding"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml.authnstatement"
|
||||
name={convertAttributeNameToForm("attributes.saml.authnstatement")}
|
||||
label="includeAuthnStatement"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml.onetimeuse.condition"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.onetimeuse.condition"
|
||||
)}
|
||||
label="includeOneTimeUseCondition"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml.server.signature.keyinfo.ext"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.server.signature.keyinfo.ext"
|
||||
)}
|
||||
label="optimizeLookup"
|
||||
/>
|
||||
</FormAccess>
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { Toggle } from "./SamlConfig";
|
||||
|
@ -48,7 +49,7 @@ export const SamlSignature = () => {
|
|||
|
||||
const { control, watch } = useFormContext<ClientRepresentation>();
|
||||
|
||||
const signDocs = watch("attributes.saml$server$signature");
|
||||
const signDocs = watch("attributes.saml.server.signature");
|
||||
const signAssertion = watch("attributes.saml.assertion.signature");
|
||||
|
||||
return (
|
||||
|
@ -57,9 +58,12 @@ export const SamlSignature = () => {
|
|||
role="manage-clients"
|
||||
className="keycloak__capability-config__form"
|
||||
>
|
||||
<Toggle name="attributes.saml$server$signature" label="signDocuments" />
|
||||
<Toggle
|
||||
name="attributes.saml.assertion.signature"
|
||||
name={convertAttributeNameToForm("attributes.saml.server.signature")}
|
||||
label="signDocuments"
|
||||
/>
|
||||
<Toggle
|
||||
name={convertAttributeNameToForm("attributes.saml.assertion.signature")}
|
||||
label="signAssertions"
|
||||
/>
|
||||
{(signDocs === "true" || signAssertion === "true") && (
|
||||
|
@ -75,7 +79,9 @@ export const SamlSignature = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml.signature.algorithm"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.signature.algorithm"
|
||||
)}
|
||||
defaultValue={SIGNATURE_ALGORITHMS[0]}
|
||||
Key
|
||||
control={control}
|
||||
|
@ -114,7 +120,9 @@ export const SamlSignature = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml$server$signature$keyinfo$xmlSigKeyInfoKeyNameTransformer"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.server.signature.keyinfo$xmlSigKeyInfoKeyNameTransformer"
|
||||
)}
|
||||
defaultValue={KEYNAME_TRANSFORMER[0]}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -17,6 +17,7 @@ import { TimeSelector } from "../../components/time-selector/TimeSelector";
|
|||
import { TokenLifespan } from "./TokenLifespan";
|
||||
import { KeyValueInput } from "../../components/key-value-form/KeyValueInput";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
type AdvancedSettingsProps = {
|
||||
control: Control<Record<string, any>>;
|
||||
|
@ -53,7 +54,9 @@ export const AdvancedSettings = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml.assertion.lifespan"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.saml.assertion.lifespan"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -70,7 +73,9 @@ export const AdvancedSettings = ({
|
|||
<>
|
||||
<TokenLifespan
|
||||
id="accessTokenLifespan"
|
||||
name="attributes.access.token.lifespan"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.access.token.lifespan"
|
||||
)}
|
||||
defaultValue=""
|
||||
units={["minute", "day", "hour"]}
|
||||
control={control}
|
||||
|
@ -114,7 +119,9 @@ export const AdvancedSettings = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.pkce.code.challenge.method"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.pkce.code.challenge.method"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -149,7 +156,9 @@ export const AdvancedSettings = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.require.pushed.authorization.requests"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.require.pushed.authorization.requests"
|
||||
)}
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -173,7 +182,9 @@ export const AdvancedSettings = ({
|
|||
/>
|
||||
}
|
||||
>
|
||||
<KeyValueInput name="attributes.acr.loa.map" />
|
||||
<KeyValueInput
|
||||
name={convertAttributeNameToForm("attributes.acr.loa.map")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("defaultACRValues")}
|
||||
|
@ -185,7 +196,9 @@ export const AdvancedSettings = ({
|
|||
/>
|
||||
}
|
||||
>
|
||||
<MultiLineInput name="attributes.default.acr.values" />
|
||||
<MultiLineInput
|
||||
name={convertAttributeNameToForm("attributes.default.acr.values")}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { sortProviders } from "../../util";
|
||||
import { convertAttributeNameToForm, sortProviders } from "../../util";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
|
||||
|
||||
|
@ -161,7 +161,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="logoUrl"
|
||||
name="attributes.logoUri"
|
||||
name={convertAttributeNameToForm("attributes.logoUri")}
|
||||
data-testid="logoUrl"
|
||||
ref={register}
|
||||
/>
|
||||
|
@ -179,7 +179,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="policyUrl"
|
||||
name="attributes.policyUri"
|
||||
name={convertAttributeNameToForm("attributes.policyUri")}
|
||||
data-testid="policyUrl"
|
||||
ref={register}
|
||||
/>
|
||||
|
@ -197,7 +197,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="termsOfServiceUrl"
|
||||
name="attributes.tosUri"
|
||||
name={convertAttributeNameToForm("attributes.tosUri")}
|
||||
data-testid="termsOfServiceUrl"
|
||||
ref={register}
|
||||
/>
|
||||
|
@ -213,7 +213,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.access.token.signed.response.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.access.token.signed.response.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -244,7 +246,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id.token.signed.response.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.id.token.signed.response.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -275,7 +279,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id.token.encrypted.response.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.id.token.encrypted.response.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -306,7 +312,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id.token.encrypted.response.enc"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.id.token.encrypted.response.enc"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -337,7 +345,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.user.info.response.signature.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.user.info.response.signature.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -368,7 +378,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.request.object.signature.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.request.object.signature.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -399,7 +411,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.request.object.encryption.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.request.object.encryption.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -430,7 +444,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.request.object.encryption.enc"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.request.object.encryption.enc"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -461,7 +477,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.request.object.required"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.request.object.required"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -492,7 +510,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<MultiLineInput
|
||||
name="attributes.request.uris"
|
||||
name={convertAttributeNameToForm("attributes.request.uris")}
|
||||
aria-label={t("validRequestURIs")}
|
||||
addButtonLabel="clients:addRequestUri"
|
||||
/>
|
||||
|
@ -508,7 +526,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.authorization.signed.response.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.authorization.signed.response.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -539,7 +559,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.authorization.encrypted.response.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.authorization.encrypted.response.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -570,7 +592,9 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.authorization.encrypted.response.enc"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.authorization.encrypted.response.enc"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ActionGroup, Button, FormGroup, Switch } from "@patternfly/react-core";
|
|||
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
type OpenIdConnectCompatibilityModesProps = {
|
||||
control: Control<Record<string, any>>;
|
||||
|
@ -37,7 +38,9 @@ export const OpenIdConnectCompatibilityModes = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.exclude.session.state.from.auth.response"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.exclude.session.state.from.auth.response"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -63,7 +66,7 @@ export const OpenIdConnectCompatibilityModes = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.use.refresh.tokens"
|
||||
name={convertAttributeNameToForm("attributes.use.refresh.tokens")}
|
||||
defaultValue="true"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -115,7 +118,9 @@ export const OpenIdConnectCompatibilityModes = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.token.response.type.bearer.lower-case"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.token.response.type.bearer.lower-case"
|
||||
)}
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { sortProviders } from "../../util";
|
||||
import { convertAttributeNameToForm, sortProviders } from "../../util";
|
||||
|
||||
export const SignedJWT = () => {
|
||||
const { control } = useFormContext();
|
||||
|
@ -32,7 +32,9 @@ export const SignedJWT = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.token.endpoint.auth.signing.alg"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.token.endpoint.auth.signing.alg"
|
||||
)}
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Controller, useFormContext } from "react-hook-form";
|
|||
import { FormGroup, Switch, ValidatedOptions } from "@patternfly/react-core";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
export const X509 = () => {
|
||||
const { t } = useTranslation("clients");
|
||||
|
@ -25,7 +26,9 @@ export const X509 = () => {
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.x509.allow.regex.pattern.comparison"
|
||||
name={convertAttributeNameToForm(
|
||||
"attributes.x509.allow.regex.pattern.comparison"
|
||||
)}
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -60,7 +63,7 @@ export const X509 = () => {
|
|||
ref={register({ required: true })}
|
||||
type="text"
|
||||
id="kc-subject"
|
||||
name="attributes.x509.subjectdn"
|
||||
name={convertAttributeNameToForm("attributes.x509.subjectdn")}
|
||||
validated={
|
||||
errors.attributes?.["x509.subjectdn"]
|
||||
? ValidatedOptions.error
|
||||
|
|
|
@ -27,6 +27,7 @@ import { GenerateKeyDialog } from "./GenerateKeyDialog";
|
|||
import { useFetch, useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
import { ImportKeyDialog, ImportFile } from "./ImportKeyDialog";
|
||||
import { Certificate } from "./Certificate";
|
||||
|
||||
|
@ -143,7 +144,7 @@ export const Keys = ({ clientId, save, hasConfigureAccess }: KeysProps) => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.use.jwks.url"
|
||||
name={convertAttributeNameToForm("attributes.use.jwks.url")}
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -178,7 +179,7 @@ export const Keys = ({ clientId, save, hasConfigureAccess }: KeysProps) => {
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="jwksUrl"
|
||||
name="attributes.jwks.url"
|
||||
name={convertAttributeNameToForm("attributes.jwks.url")}
|
||||
ref={register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { FormGroup, Switch } from "@patternfly/react-core";
|
|||
|
||||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const BooleanComponent = ({
|
||||
name,
|
||||
|
@ -25,7 +26,7 @@ export const BooleanComponent = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
data-testid={name}
|
||||
defaultValue={defaultValue || false}
|
||||
control={control}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import type { ComponentProps } from "./components";
|
||||
import { ClientSelect } from "../client/ClientSelect";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const ClientSelectComponent = (props: ComponentProps) => {
|
||||
return (
|
||||
<ClientSelect
|
||||
{...props}
|
||||
name={`config.${props.name}`}
|
||||
name={convertToName(props.name!)}
|
||||
namespace="dynamic"
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { ConfigPropertyRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigInfoRepresentation";
|
||||
|
||||
import { COMPONENTS, isValidComponentType } from "./components";
|
||||
import { convertAttributeNameToForm } from "../../util";
|
||||
|
||||
type DynamicComponentProps = {
|
||||
properties: ConfigPropertyRepresentation[];
|
||||
|
@ -24,3 +25,6 @@ export const DynamicComponents = ({
|
|||
})}
|
||||
</>
|
||||
);
|
||||
|
||||
export const convertToName = (name: string) =>
|
||||
convertAttributeNameToForm(`config.${name}`);
|
||||
|
|
|
@ -5,6 +5,7 @@ import { FileUpload, FormGroup } from "@patternfly/react-core";
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const FileComponent = ({
|
||||
name,
|
||||
|
@ -26,7 +27,7 @@ export const FileComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
control={control}
|
||||
defaultValue={defaultValue || ""}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { GroupPickerDialog } from "../group/GroupPickerDialog";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const GroupComponent = ({ name, label, helpText }: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
|
@ -20,7 +21,7 @@ export const GroupComponent = ({ name, label, helpText }: ComponentProps) => {
|
|||
|
||||
return (
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
defaultValue=""
|
||||
typeAheadAriaLabel={t("selectGroup")}
|
||||
control={control}
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
|
||||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const ListComponent = ({
|
||||
name,
|
||||
|
@ -32,7 +33,7 @@ export const ListComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
data-testid={name}
|
||||
defaultValue={defaultValue || ""}
|
||||
control={control}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { FormGroup } from "@patternfly/react-core";
|
|||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { KeyValueInput } from "../key-value-form/KeyValueInput";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const MapComponent = ({ name, label, helpText }: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
|
@ -16,7 +17,7 @@ export const MapComponent = ({ name, label, helpText }: ComponentProps) => {
|
|||
}
|
||||
fieldId={name!}
|
||||
>
|
||||
<KeyValueInput name={`config.${name}`} />
|
||||
<KeyValueInput name={convertToName(name!)} />
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const MultiValuedListComponent = ({
|
||||
name,
|
||||
|
@ -32,7 +33,7 @@ export const MultiValuedListComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
control={control}
|
||||
defaultValue={defaultValue ? [defaultValue] : []}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -4,6 +4,7 @@ import { FormGroup } from "@patternfly/react-core";
|
|||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { MultiLineInput } from "../multi-line-input/MultiLineInput";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const MultiValuedStringComponent = ({
|
||||
name,
|
||||
|
@ -13,7 +14,7 @@ export const MultiValuedStringComponent = ({
|
|||
isDisabled = false,
|
||||
}: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
const fieldName = `config.${name}`;
|
||||
const fieldName = convertToName(name!);
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
|
|
|
@ -18,6 +18,7 @@ import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
|||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
const RealmClient = (realm: string): ClientRepresentation => ({
|
||||
name: "realmRoles",
|
||||
|
@ -47,7 +48,7 @@ export const RoleComponent = ({
|
|||
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
|
||||
const [selectedRole, setSelectedRole] = useState<RoleRepresentation>();
|
||||
|
||||
const fieldName = `config.${name}`;
|
||||
const fieldName = convertToName(name!);
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { CodeEditor, Language } from "@patternfly/react-code-editor";
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const ScriptComponent = ({
|
||||
name,
|
||||
|
@ -28,7 +29,7 @@ export const ScriptComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
defaultValue={defaultValue}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -5,6 +5,7 @@ import { FormGroup } from "@patternfly/react-core";
|
|||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { KeycloakTextInput } from "../keycloak-text-input/KeycloakTextInput";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
|
||||
export const StringComponent = ({
|
||||
name,
|
||||
|
@ -30,7 +31,7 @@ export const StringComponent = ({
|
|||
isDisabled={isDisabled}
|
||||
ref={register()}
|
||||
type="text"
|
||||
name={`config.${name}`}
|
||||
name={convertToName(name!)}
|
||||
defaultValue={defaultValue?.toString()}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -166,8 +166,10 @@ export default function AddMapper() {
|
|||
|
||||
const setupForm = (mapper: IdentityProviderMapperRepresentation) => {
|
||||
convertToFormValues(mapper, form.setValue);
|
||||
form.setValue("config.attributes", JSON.parse(mapper.config.attributes));
|
||||
form.setValue("config.claims", JSON.parse(mapper.config.claims));
|
||||
form.setValue(
|
||||
"config.attributes",
|
||||
JSON.parse(mapper.config.attributes || "{}")
|
||||
);
|
||||
};
|
||||
|
||||
if (!mapperTypes || !currentMapper) {
|
||||
|
@ -241,7 +243,7 @@ export default function AddMapper() {
|
|||
/>
|
||||
<FormProvider {...form}>
|
||||
<DynamicComponents properties={currentMapper.properties!} />
|
||||
</FormProvider>{" "}
|
||||
</FormProvider>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
@ -16,7 +16,11 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { addTrailingSlash, convertToFormValues } from "../util";
|
||||
import {
|
||||
addTrailingSlash,
|
||||
convertAttributeNameToForm,
|
||||
convertToFormValues,
|
||||
} from "../util";
|
||||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
@ -58,7 +62,7 @@ export const RealmSettingsGeneralTab = ({
|
|||
JSON.parse(realm.attributes["acr.loa.map"])
|
||||
).flatMap(([key, value]) => ({ key, value }));
|
||||
result.concat({ key: "", value: "" });
|
||||
setValue("attributes.acr.loa.map", result);
|
||||
setValue(convertAttributeNameToForm("attributes.acr.loa.map"), result);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -113,7 +117,7 @@ export const RealmSettingsGeneralTab = ({
|
|||
<KeycloakTextInput
|
||||
type="text"
|
||||
id="kc-frontend-url"
|
||||
name="attributes.frontendUrl"
|
||||
name={convertAttributeNameToForm("attributes.frontendUrl")}
|
||||
ref={register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -168,7 +172,9 @@ export const RealmSettingsGeneralTab = ({
|
|||
}
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<KeyValueInput name="attributes.acr.loa.map" />
|
||||
<KeyValueInput
|
||||
name={convertAttributeNameToForm("attributes.acr.loa.map")}
|
||||
/>
|
||||
</FormProvider>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
|
@ -211,7 +217,7 @@ export const RealmSettingsGeneralTab = ({
|
|||
fieldId="kc-user-profile-enabled"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.userProfileEnabled"
|
||||
name={convertAttributeNameToForm("attributes.userProfileEnabled")}
|
||||
control={control}
|
||||
defaultValue={false}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
import { convertFormValuesToObject, convertToFormValues } from "./util";
|
||||
import {
|
||||
convertAttributeNameToForm,
|
||||
convertFormValuesToObject,
|
||||
convertToFormValues,
|
||||
} from "./util";
|
||||
|
||||
vi.mock("react");
|
||||
|
||||
const TOKEN = "🍺";
|
||||
|
||||
describe("Tests the form convert util functions", () => {
|
||||
it("convert to form values", () => {
|
||||
const given = {
|
||||
|
@ -31,7 +37,7 @@ describe("Tests the form convert util functions", () => {
|
|||
const given = {
|
||||
name: "client",
|
||||
attributes: [{ key: "one", value: "1" }],
|
||||
config: { one: { two: "3" } },
|
||||
config: { [`one${TOKEN}two`]: "3" },
|
||||
};
|
||||
|
||||
//when
|
||||
|
@ -51,10 +57,10 @@ describe("Tests the form convert util functions", () => {
|
|||
description: "",
|
||||
type: "default",
|
||||
attributes: {
|
||||
display: { on: { consent: { screen: "true" } } },
|
||||
include: { in: { token: { scope: "true" } } },
|
||||
gui: { order: "1" },
|
||||
consent: { screen: { text: "" } },
|
||||
[`display${TOKEN}on${TOKEN}consent${TOKEN}screen`]: "true",
|
||||
[`include${TOKEN}in${TOKEN}token${TOKEN}scope`]: "true",
|
||||
[`gui${TOKEN}order`]: "1",
|
||||
[`consent${TOKEN}screen${TOKEN}text`]: "",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -92,12 +98,10 @@ describe("Tests the form convert util functions", () => {
|
|||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
attributes: {
|
||||
display: { on: { consent: { screen: "true" } } },
|
||||
include: { in: { token: { scope: "true" } } },
|
||||
gui: { order: "1" },
|
||||
consent: { screen: { text: "" } },
|
||||
},
|
||||
[`attributes.display${TOKEN}on${TOKEN}consent${TOKEN}screen`]: "true",
|
||||
[`attributes.include${TOKEN}in${TOKEN}token${TOKEN}scope`]: "true",
|
||||
[`attributes.gui${TOKEN}order`]: "1",
|
||||
[`attributes.consent${TOKEN}screen${TOKEN}text`]: "",
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -115,17 +119,31 @@ describe("Tests the form convert util functions", () => {
|
|||
|
||||
it("convert single element arrays to string", () => {
|
||||
const given = {
|
||||
config: { group: ["one"], another: { nested: ["value"] } },
|
||||
config: {
|
||||
group: ["one"],
|
||||
"another.nested": ["value"],
|
||||
},
|
||||
};
|
||||
const setValue = vi.fn();
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues(given, setValue);
|
||||
convertToFormValues(given, spy);
|
||||
|
||||
//then
|
||||
expect(setValue).toHaveBeenCalledWith("config", {
|
||||
group: "one",
|
||||
another: { nested: "value" },
|
||||
expect(values).toEqual({
|
||||
"config.group": "one",
|
||||
[`config.another${TOKEN}nested`]: "value",
|
||||
});
|
||||
});
|
||||
|
||||
it("should convert attribute name to form", () => {
|
||||
const given = "attributes.some.strange.attribute";
|
||||
|
||||
//when
|
||||
const form = convertAttributeNameToForm(given);
|
||||
|
||||
//then
|
||||
expect(form).toEqual(`attributes.some${TOKEN}strange${TOKEN}attribute`);
|
||||
});
|
||||
});
|
||||
|
|
24
src/util.ts
24
src/util.ts
|
@ -1,7 +1,7 @@
|
|||
import { cloneDeep } from "lodash-es";
|
||||
import FileSaver from "file-saver";
|
||||
import type { IFormatter, IFormatterValueType } from "@patternfly/react-table";
|
||||
import { unflatten, flatten } from "flat";
|
||||
import { flatten } from "flat";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import type { ProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
||||
|
@ -85,6 +85,16 @@ const isAttributeArray = (value: any) => {
|
|||
|
||||
const isEmpty = (obj: any) => Object.keys(obj).length === 0;
|
||||
|
||||
export const convertAttributeNameToForm = (name: string) => {
|
||||
const index = name.indexOf(".");
|
||||
return `${name.substring(0, index)}.${convertAttribute(
|
||||
name.substring(index + 1)
|
||||
)}`;
|
||||
};
|
||||
|
||||
const convertAttribute = (name: string) => name.replace(/\./g, "🍺");
|
||||
const convertFormNameToAttribute = (name: string) => name.replace(/🍺/g, ".");
|
||||
|
||||
export const convertToFormValues = (
|
||||
obj: any,
|
||||
setValue: (name: string, value: any) => void
|
||||
|
@ -98,7 +108,10 @@ export const convertToFormValues = (
|
|||
const convertedValues = Object.entries(flattened).map(([key, value]) =>
|
||||
Array.isArray(value) ? [key, value[0]] : [key, value]
|
||||
);
|
||||
setValue(key, unflatten(Object.fromEntries(convertedValues)));
|
||||
|
||||
convertedValues.forEach(([k, v]) =>
|
||||
setValue(`${key}.${convertAttribute(k)}`, v)
|
||||
);
|
||||
} else {
|
||||
setValue(key, undefined);
|
||||
}
|
||||
|
@ -114,7 +127,12 @@ export function convertFormValuesToObject<T, G = T>(obj: T): G {
|
|||
if (isAttributeArray(value)) {
|
||||
result[key] = keyValueToArray(value as KeyValueType[]);
|
||||
} else if (key === "config" || key === "attributes") {
|
||||
result[key] = flatten(value as Record<string, any>, { safe: true });
|
||||
result[key] = Object.fromEntries(
|
||||
Object.entries(value).map(([k, v]) => [
|
||||
convertFormNameToAttribute(k),
|
||||
v,
|
||||
])
|
||||
);
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue