better form convert (#1640)
* better form convert * fixed other forms * changed to use npm package * better form convert * merge fix * fixed mapper test
This commit is contained in:
parent
1f568d8888
commit
242c1d8445
53 changed files with 433 additions and 484 deletions
27
package-lock.json
generated
27
package-lock.json
generated
|
@ -15,6 +15,7 @@
|
|||
"@patternfly/react-table": "^4.44.4",
|
||||
"dagre": "^0.8.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"flat": "^5.0.2",
|
||||
"i18next": "^21.5.5",
|
||||
"lodash": "^4.17.20",
|
||||
"moment": "^2.29.1",
|
||||
|
@ -41,6 +42,7 @@
|
|||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/dagre": "^0.7.45",
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/flat": "^5.0.2",
|
||||
"@types/lodash": "^4.14.177",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/react": "^17.0.37",
|
||||
|
@ -4873,6 +4875,12 @@
|
|||
"integrity": "sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-3zsplnP2djeps5P9OyarTxwRpMLoe5Ash8aL9iprw0JxB+FAHjY+ifn4yZUuW4/9hqtnmor6uvjSRzJhiVbrEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/geojson": {
|
||||
"version": "7946.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
|
||||
|
@ -10616,6 +10624,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
|
||||
"bin": {
|
||||
"flat": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
|
@ -25327,6 +25343,12 @@
|
|||
"integrity": "sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-3zsplnP2djeps5P9OyarTxwRpMLoe5Ash8aL9iprw0JxB+FAHjY+ifn4yZUuW4/9hqtnmor6uvjSRzJhiVbrEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/geojson": {
|
||||
"version": "7946.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
|
||||
|
@ -29871,6 +29893,11 @@
|
|||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"@patternfly/react-table": "^4.44.4",
|
||||
"dagre": "^0.8.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"flat": "^5.0.2",
|
||||
"i18next": "^21.5.5",
|
||||
"lodash": "^4.17.20",
|
||||
"moment": "^2.29.1",
|
||||
|
@ -57,6 +58,7 @@
|
|||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/dagre": "^0.7.45",
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/flat": "^5.0.2",
|
||||
"@types/lodash": "^4.14.177",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/react": "^17.0.37",
|
||||
|
|
|
@ -115,12 +115,7 @@ export default function MappingDetails() {
|
|||
setConfig(config);
|
||||
setMapping(mapping);
|
||||
if (data) {
|
||||
Object.entries(data).map(([key, value]) => {
|
||||
if (key === "config") {
|
||||
convertToFormValues(value, "config", setValue);
|
||||
}
|
||||
setValue(key, value);
|
||||
});
|
||||
convertToFormValues(data, setValue);
|
||||
}
|
||||
},
|
||||
[]
|
||||
|
@ -153,10 +148,9 @@ export default function MappingDetails() {
|
|||
});
|
||||
|
||||
const save = async (formMapping: ProtocolMapperRepresentation) => {
|
||||
const configAttributes = convertFormValuesToObject(formMapping.config);
|
||||
const key = isUpdating ? "Updated" : "Created";
|
||||
try {
|
||||
const mapping = { ...formMapping, ...config, config: configAttributes };
|
||||
const mapping = { ...config, ...convertFormValuesToObject(formMapping) };
|
||||
if (isUpdating) {
|
||||
isOnClientScope
|
||||
? await adminClient.clientScopes.updateProtocolMapper(
|
||||
|
|
|
@ -40,7 +40,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
const { t: tc } = useTranslation("clients");
|
||||
const { register, control, handleSubmit, errors, setValue } =
|
||||
useForm<ClientScopeRepresentation>({
|
||||
defaultValues: { attributes: { "display-on-consent-screen": "true" } },
|
||||
defaultValues: { attributes: { "display.on.consent.screen": "true" } },
|
||||
});
|
||||
const { realm } = useRealm();
|
||||
|
||||
|
@ -51,16 +51,11 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
|
||||
const displayOnConsentScreen = useWatch({
|
||||
control,
|
||||
name: "attributes.display-on-consent-screen",
|
||||
name: "attributes.display.on.consent.screen",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
Object.entries(clientScope).map((entry) => {
|
||||
if (entry[0] === "attributes") {
|
||||
convertToFormValues(entry[1], "attributes", setValue);
|
||||
}
|
||||
setValue(entry[0], entry[1]);
|
||||
});
|
||||
convertToFormValues(clientScope, setValue);
|
||||
}, [clientScope]);
|
||||
|
||||
return (
|
||||
|
@ -213,7 +208,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="kc-display.on.consent.screen"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.display-on-consent-screen"
|
||||
name="attributes.display.on.consent.screen"
|
||||
control={control}
|
||||
defaultValue="true"
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -243,7 +238,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
ref={register}
|
||||
type="text"
|
||||
id="kc-consent-screen-text"
|
||||
name="attributes.consent-screen-text"
|
||||
name="attributes.consent.screen.text"
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
|
@ -260,7 +255,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="includeInTokenScope"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.include-in-token-scope"
|
||||
name="attributes.include.in.token.scope"
|
||||
control={control}
|
||||
defaultValue="true"
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -286,7 +281,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
fieldId="kc-gui-order"
|
||||
>
|
||||
<Controller
|
||||
name="attributes.gui-order"
|
||||
name="attributes.gui.order"
|
||||
defaultValue={1}
|
||||
control={control}
|
||||
render={({ onChange, value }) => {
|
||||
|
|
|
@ -107,9 +107,9 @@ export default function ClientScopeForm() {
|
|||
const save = async (clientScopes: ClientScopeDefaultOptionalType) => {
|
||||
try {
|
||||
clientScopes.name = clientScopes.name?.trim();
|
||||
clientScopes.attributes = convertFormValuesToObject(
|
||||
clientScopes.attributes!
|
||||
);
|
||||
clientScopes = convertFormValuesToObject(
|
||||
clientScopes
|
||||
) as ClientScopeDefaultOptionalType;
|
||||
|
||||
if (id) {
|
||||
await adminClient.clientScopes.update({ id }, clientScopes);
|
||||
|
|
|
@ -104,9 +104,7 @@ export const AdvancedTab = ({
|
|||
const resetFields = (names: string[]) => {
|
||||
const values: { [name: string]: string } = {};
|
||||
for (const name of names) {
|
||||
values[`attributes.${name}`] = attributes
|
||||
? attributes[name.replace(/-/g, ".")] || ""
|
||||
: "";
|
||||
values[`attributes.${name}`] = attributes?.[name];
|
||||
}
|
||||
reset(values);
|
||||
};
|
||||
|
@ -385,7 +383,9 @@ export const AdvancedTab = ({
|
|||
control={control}
|
||||
save={() => save()}
|
||||
reset={() =>
|
||||
convertToFormValues(attributes, "attributes", setValue)
|
||||
convertToFormValues(attributes, (key, value) =>
|
||||
setValue(`attributes.${key}`, value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -399,7 +399,9 @@ export const AdvancedTab = ({
|
|||
control={control}
|
||||
save={() => save()}
|
||||
reset={() =>
|
||||
convertToFormValues(attributes, "attributes", setValue)
|
||||
convertToFormValues(attributes, (key, value) =>
|
||||
setValue(`attributes.${key}`, value)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -414,7 +416,7 @@ export const AdvancedTab = ({
|
|||
control={control}
|
||||
save={() => save()}
|
||||
reset={() =>
|
||||
resetFields(["exclude-session-state-from-auth-response"])
|
||||
resetFields(["exclude.session.state.from.auth.response"])
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -429,10 +431,10 @@ export const AdvancedTab = ({
|
|||
save={() => save()}
|
||||
reset={() => {
|
||||
resetFields([
|
||||
"saml-assertion-lifespan",
|
||||
"access-token-lifespan",
|
||||
"tls-client-certificate-bound-access-tokens",
|
||||
"pkce-code-challenge-method",
|
||||
"saml.assertion.lifespan",
|
||||
"access.token.lifespan",
|
||||
"tls.client.certificate.bound.access.tokens",
|
||||
"pkce.code.challenge.method",
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
import { InfoCircleIcon } from "@patternfly/react-icons";
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import _ from "lodash";
|
||||
import _, { cloneDeep } from "lodash";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
@ -25,11 +25,7 @@ import {
|
|||
} from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { DownloadDialog } from "../components/download-dialog/DownloadDialog";
|
||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||
import {
|
||||
convertToMultiline,
|
||||
MultiLine,
|
||||
toValue,
|
||||
} from "../components/multi-line-input/MultiLineInput";
|
||||
import type { MultiLine } from "../components/multi-line-input/multi-line-convert";
|
||||
import {
|
||||
ViewHeader,
|
||||
ViewHeaderBadge,
|
||||
|
@ -219,18 +215,7 @@ export default function ClientDetails() {
|
|||
});
|
||||
|
||||
const setupForm = (client: ClientRepresentation) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { redirectUris, webOrigins, ...formValues } = client;
|
||||
form.reset(formValues);
|
||||
Object.entries(client).map((entry) => {
|
||||
if (entry[0] === "redirectUris" || entry[0] === "webOrigins") {
|
||||
form.setValue(entry[0], convertToMultiline(entry[1]));
|
||||
} else if (entry[0] === "attributes") {
|
||||
convertToFormValues(entry[1], "attributes", form.setValue);
|
||||
} else {
|
||||
form.setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
convertToFormValues(client, form.setValue, ["redirectUris", "webOrigins"]);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
@ -239,7 +224,7 @@ export default function ClientDetails() {
|
|||
if (!fetchedClient) {
|
||||
throw new Error(t("common:notFound"));
|
||||
}
|
||||
setClient(fetchedClient);
|
||||
setClient(cloneDeep(fetchedClient));
|
||||
setupForm(fetchedClient);
|
||||
},
|
||||
[clientId]
|
||||
|
@ -260,19 +245,15 @@ export default function ClientDetails() {
|
|||
toggleChangeAuthenticatorOpen();
|
||||
return;
|
||||
}
|
||||
const redirectUris = toValue(form.getValues()["redirectUris"]);
|
||||
const webOrigins = toValue(form.getValues()["webOrigins"]);
|
||||
const attributes = convertFormValuesToObject(
|
||||
form.getValues()["attributes"]
|
||||
);
|
||||
const submittedClient = convertFormValuesToObject(form.getValues(), [
|
||||
"redirectUris",
|
||||
"webOrigins",
|
||||
]);
|
||||
|
||||
try {
|
||||
const newClient: ClientRepresentation = {
|
||||
...client,
|
||||
...form.getValues(),
|
||||
redirectUris,
|
||||
webOrigins,
|
||||
attributes,
|
||||
...submittedClient,
|
||||
};
|
||||
|
||||
newClient.clientId = newClient.clientId?.trim();
|
||||
|
@ -282,7 +263,7 @@ export default function ClientDetails() {
|
|||
setClient(newClient);
|
||||
addAlert(t(messageKey), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("client:clientSaveError", error);
|
||||
addError("clients:clientSaveError", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,7 +43,7 @@ export const ClientSettings = ({
|
|||
const loginThemes = useServerInfo().themes!["login"];
|
||||
const consentRequired = watch("consentRequired");
|
||||
const displayOnConsentScreen: string = watch(
|
||||
"attributes.display-on-consent-screen"
|
||||
"attributes.display.on.consent.screen"
|
||||
);
|
||||
const protocol = watch("protocol");
|
||||
|
||||
|
@ -250,7 +250,7 @@ export const ClientSettings = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.display-on-consent-screen"
|
||||
name="attributes.display.on.consent.screen"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -278,7 +278,7 @@ export const ClientSettings = ({
|
|||
>
|
||||
<TextArea
|
||||
id="kc-consent-screen-text"
|
||||
name="attributes.consent-screen-text"
|
||||
name="attributes.consent.screen.text"
|
||||
ref={register}
|
||||
isDisabled={!(consentRequired && displayOnConsentScreen === "true")}
|
||||
/>
|
||||
|
|
|
@ -248,7 +248,7 @@ export const CapabilityConfig = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml-encrypt"
|
||||
name="attributes.saml.encrypt"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -276,7 +276,7 @@ export const CapabilityConfig = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml-client-signature"
|
||||
name="attributes.saml.client.signature"
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -44,15 +44,10 @@ export default function NewClientForm() {
|
|||
const methods = useForm<ClientRepresentation>({ defaultValues: client });
|
||||
|
||||
const save = async () => {
|
||||
const attributes = client.attributes
|
||||
? convertFormValuesToObject(client.attributes)
|
||||
: undefined;
|
||||
|
||||
try {
|
||||
const newClient = await adminClient.clients.create({
|
||||
...client,
|
||||
...convertFormValuesToObject(client),
|
||||
clientId: client.clientId?.trim(),
|
||||
attributes,
|
||||
});
|
||||
addAlert(t("createSuccess"), AlertVariant.success);
|
||||
history.push(
|
||||
|
@ -65,15 +60,21 @@ export default function NewClientForm() {
|
|||
|
||||
const forward = async (onNext?: () => void) => {
|
||||
if (await methods.trigger()) {
|
||||
setClient({ ...client, ...methods.getValues() });
|
||||
setClient({
|
||||
...client,
|
||||
...convertFormValuesToObject(methods.getValues()),
|
||||
});
|
||||
setShowCapabilityConfig(true);
|
||||
onNext?.();
|
||||
}
|
||||
};
|
||||
|
||||
const back = () => {
|
||||
setClient({ ...client, ...methods.getValues() });
|
||||
methods.reset({ ...client, ...methods.getValues() });
|
||||
setClient({ ...client, ...convertFormValuesToObject(methods.getValues()) });
|
||||
methods.reset({
|
||||
...client,
|
||||
...convertFormValuesToObject(methods.getValues()),
|
||||
});
|
||||
};
|
||||
|
||||
const onGoToStep = (newStep: { id?: string | number }) => {
|
||||
|
|
|
@ -100,23 +100,23 @@ export const SamlConfig = () => {
|
|||
/>
|
||||
</FormGroup>
|
||||
<Toggle
|
||||
name="attributes.saml_force_name_id_format"
|
||||
name="attributes.saml.force.name.id.format"
|
||||
label="forceNameIdFormat"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml-force-post-binding"
|
||||
name="attributes.saml.force.post.binding"
|
||||
label="forcePostBinding"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml-artifact-binding"
|
||||
name="attributes.saml.artifact.binding"
|
||||
label="forceArtifactBinding"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml-onetimeuse-condition"
|
||||
name="attributes.saml.onetimeuse.condition"
|
||||
label="includeOneTimeUseCondition"
|
||||
/>
|
||||
<Toggle
|
||||
name="attributes.saml-server-signature-keyinfo-ext"
|
||||
name="attributes.saml.server.signature.keyinfo.ext"
|
||||
label="optimizeLookup"
|
||||
/>
|
||||
</FormAccess>
|
||||
|
|
|
@ -48,8 +48,8 @@ export const SamlSignature = () => {
|
|||
|
||||
const { control, watch } = useFormContext<ClientForm>();
|
||||
|
||||
const signDocs = watch("attributes.saml-server-signature");
|
||||
const signAssertion = watch("attributes.saml-assertion-signature");
|
||||
const signDocs = watch("attributes.saml.server.signature");
|
||||
const signAssertion = watch("attributes.saml.assertion.signature");
|
||||
|
||||
return (
|
||||
<FormAccess
|
||||
|
@ -57,9 +57,9 @@ export const SamlSignature = () => {
|
|||
role="manage-clients"
|
||||
className="keycloak__capability-config__form"
|
||||
>
|
||||
<Toggle name="attributes.saml-server-signature" label="signDocuments" />
|
||||
<Toggle name="attributes.saml.server.signature" label="signDocuments" />
|
||||
<Toggle
|
||||
name="attributes.saml-assertion-signature"
|
||||
name="attributes.saml.assertion.signature"
|
||||
label="signAssertions"
|
||||
/>
|
||||
{(signDocs === "true" || signAssertion === "true") && (
|
||||
|
@ -78,7 +78,7 @@ export const SamlSignature = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml-signature-algorithm"
|
||||
name="attributes.saml.signature.algorithm"
|
||||
defaultValue={SIGNATURE_ALGORITHMS[0]}
|
||||
Key
|
||||
control={control}
|
||||
|
@ -120,7 +120,7 @@ export const SamlSignature = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml-server-signature-keyinfo-xmlSigKeyInfoKeyNameTransformer"
|
||||
name="attributes.saml.server.signature.keyinfo.xmlSigKeyInfoKeyNameTransformer"
|
||||
defaultValue={KEYNAME_TRANSFORMER[0]}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -46,7 +46,7 @@ export const AdvancedSettings = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.saml-assertion-lifespan"
|
||||
name="attributes.saml.assertion.lifespan"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -63,7 +63,7 @@ export const AdvancedSettings = ({
|
|||
<>
|
||||
<TokenLifespan
|
||||
id="accessTokenLifespan"
|
||||
name="attributes.access-token-lifespan"
|
||||
name="attributes.access.token.lifespan"
|
||||
defaultValue=""
|
||||
units={["minutes", "days", "hours"]}
|
||||
control={control}
|
||||
|
@ -111,7 +111,7 @@ export const AdvancedSettings = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.pkce-code-challenge-method"
|
||||
name="attributes.pkce.code.challenge.method"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -100,10 +100,6 @@ export const FineGrainOpenIdConnect = ({
|
|||
</SelectOption>
|
||||
));
|
||||
|
||||
const selectOptionToString = (value: string, options: JSX.Element[]) => {
|
||||
const selectOption = options.find((s) => s.props.value === value);
|
||||
return selectOption?.props.children || selectOption?.props.value;
|
||||
};
|
||||
return (
|
||||
<FormAccess role="manage-clients" isHorizontal>
|
||||
<FormGroup
|
||||
|
@ -118,7 +114,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.access-token-signed-response-alg"
|
||||
name="attributes.access.token.signed.response.alg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -131,7 +127,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setAccessTokenOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, keyOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{keyOptions}
|
||||
</Select>
|
||||
|
@ -150,7 +146,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id-token-signed-response-alg"
|
||||
name="attributes.id.token.signed.response.alg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -163,7 +159,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setIdTokenOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, keyOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{keyOptions}
|
||||
</Select>
|
||||
|
@ -182,7 +178,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id-token-encrypted-response-alg"
|
||||
name="attributes.id.token.encrypted.response.alg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -195,7 +191,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setIdTokenKeyManagementOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, cekManagementOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{cekManagementOptions}
|
||||
</Select>
|
||||
|
@ -214,7 +210,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.id-token-encrypted-response-enc"
|
||||
name="attributes.id.token.encrypted.response.enc"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -227,7 +223,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setIdTokenContentOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, contentOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{contentOptions}
|
||||
</Select>
|
||||
|
@ -246,7 +242,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.user-info-response-signature-alg"
|
||||
name="attributes.user.info.response.signature.alg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -259,7 +255,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setUserInfoSignedResponseOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, signatureOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{signatureOptions}
|
||||
</Select>
|
||||
|
@ -291,7 +287,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setRequestObjectSignatureOpen(false);
|
||||
}}
|
||||
selections={[selectOptionToString(value, requestObjectOptions)]}
|
||||
selections={value}
|
||||
>
|
||||
{requestObjectOptions}
|
||||
</Select>
|
||||
|
@ -310,7 +306,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.request-object-required"
|
||||
name="attributes.request.object.required"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -323,9 +319,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
onChange(value);
|
||||
setRequestObjectRequiredOpen(false);
|
||||
}}
|
||||
selections={[
|
||||
selectOptionToString(value, requestObjectRequiredOptions),
|
||||
]}
|
||||
selections={value}
|
||||
>
|
||||
{requestObjectRequiredOptions}
|
||||
</Select>
|
||||
|
|
|
@ -27,19 +27,12 @@ import { ViewHeader } from "../../components/view-header/ViewHeader";
|
|||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
convertToMultiline,
|
||||
MultiLine,
|
||||
MultiLineInput,
|
||||
toValue,
|
||||
} from "../../components/multi-line-input/MultiLineInput";
|
||||
import type { MultiLine } from "../../components/multi-line-input/multi-line-convert";
|
||||
import type { KeyValueType } from "../../components/attribute-form/attribute-convert";
|
||||
import { convertFormValuesToObject, convertToFormValues } from "../../util";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
import { toClient } from "../routes/Client";
|
||||
import { ScopePicker } from "./ScopePicker";
|
||||
import {
|
||||
arrayToAttributes,
|
||||
attributesToArray,
|
||||
KeyValueType,
|
||||
} from "../../components/attribute-form/attribute-convert";
|
||||
import { AttributeInput } from "../../components/attribute-input/AttributeInput";
|
||||
|
||||
import "./resource-details.css";
|
||||
|
@ -75,15 +68,7 @@ export default function ResourceDetails() {
|
|||
const history = useHistory();
|
||||
|
||||
const setupForm = (resource: ResourceRepresentation = {}) => {
|
||||
Object.entries(resource).forEach(([key, value]) => {
|
||||
if (key === "uris") {
|
||||
setValue("uris", convertToMultiline(value));
|
||||
} else if (key === "attributes") {
|
||||
setValue("attributes", attributesToArray(value));
|
||||
} else {
|
||||
setValue(key, value);
|
||||
}
|
||||
});
|
||||
convertToFormValues(resource, setValue, ["uris"]);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
@ -113,12 +98,7 @@ export default function ResourceDetails() {
|
|||
);
|
||||
|
||||
const save = async (submitted: SubmittedResource) => {
|
||||
const { attributes, uris, ...rest } = submitted;
|
||||
const resource = {
|
||||
...rest,
|
||||
attributes: arrayToAttributes(attributes),
|
||||
uris: toValue(uris),
|
||||
};
|
||||
const resource = convertFormValuesToObject(submitted, ["uris"]);
|
||||
|
||||
try {
|
||||
if (resourceId) {
|
||||
|
|
|
@ -33,7 +33,7 @@ export const SignedJWT = () => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.token-endpoint-auth-signing-alg"
|
||||
name="attributes.token.endpoint.auth.signing.alg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -20,7 +20,7 @@ export const X509 = () => {
|
|||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
validated={
|
||||
errors.attributes?.["x509-subjectdn"]
|
||||
errors.attributes?.["x509.subjectdn"]
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ export const X509 = () => {
|
|||
ref={register({ required: true })}
|
||||
type="text"
|
||||
id="kc-subject"
|
||||
name="attributes.x509-subjectdn"
|
||||
name="attributes.x509.subjectdn"
|
||||
validated={
|
||||
errors.attributes?.["x509-subjectdn"]
|
||||
errors.attributes?.["x509.subjectdn"]
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export default function ImportForm() {
|
|||
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const handleFileChange = (obj: object) => {
|
||||
const handleFileChange = (obj?: object) => {
|
||||
const defaultClient = {
|
||||
protocol: "",
|
||||
clientId: "",
|
||||
|
@ -42,13 +42,7 @@ export default function ImportForm() {
|
|||
description: "",
|
||||
};
|
||||
|
||||
Object.entries(obj || defaultClient).forEach((entries) => {
|
||||
if (entries[0] === "attributes") {
|
||||
convertToFormValues(entries[1], "attributes", form.setValue);
|
||||
} else {
|
||||
setValue(entries[0], entries[1]);
|
||||
}
|
||||
});
|
||||
convertToFormValues(obj || defaultClient, setValue);
|
||||
setImported(obj || defaultClient);
|
||||
};
|
||||
|
||||
|
@ -56,8 +50,7 @@ export default function ImportForm() {
|
|||
try {
|
||||
const newClient = await adminClient.clients.create({
|
||||
...imported,
|
||||
...client,
|
||||
attributes: convertFormValuesToObject(client.attributes || {}),
|
||||
...convertFormValuesToObject(client),
|
||||
});
|
||||
addAlert(t("clientImportSuccess"), AlertVariant.success);
|
||||
history.push(
|
||||
|
|
|
@ -54,7 +54,7 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
|
||||
const useJwksUrl = useWatch({
|
||||
control,
|
||||
name: "attributes.use-jwks-url",
|
||||
name: "attributes.use.jwks.url",
|
||||
defaultValue: "false",
|
||||
});
|
||||
|
||||
|
@ -137,7 +137,7 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name="attributes.use-jwks-url"
|
||||
name="attributes.use.jwks.url"
|
||||
defaultValue="false"
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -173,7 +173,7 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
<TextInput
|
||||
type="text"
|
||||
id="jwksUrl"
|
||||
name="attributes.jwks-url"
|
||||
name="attributes.jwks.url"
|
||||
ref={register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -38,12 +38,12 @@ export type KeyTypes = typeof KEYS[number];
|
|||
|
||||
const KEYS_MAPPING: { [key in KeyTypes]: { [index: string]: string } } = {
|
||||
"saml.signing": {
|
||||
name: "attributes.saml-client-signature",
|
||||
name: "attributes.saml.client.signature",
|
||||
title: "signingKeysConfig",
|
||||
key: "clientSignature",
|
||||
},
|
||||
"saml.encryption": {
|
||||
name: "attributes.saml-encrypt",
|
||||
name: "attributes.saml.encrypt",
|
||||
title: "encryptionKeysConfig",
|
||||
key: "encryptAssertions",
|
||||
},
|
||||
|
|
|
@ -127,7 +127,7 @@ export default {
|
|||
createError: "Could not create client: '{{error}}'",
|
||||
clientImportError: "Could not import client: {{error}}",
|
||||
clientSaveSuccess: "Client successfully updated",
|
||||
clientSaveError: "Client could not be updated:",
|
||||
clientSaveError: "Client could not be updated: {{error}}",
|
||||
clientImportSuccess: "Client imported successfully",
|
||||
clientDelete: "Delete {{clientId}} ?",
|
||||
clientDeletedSuccess: "The client has been deleted",
|
||||
|
|
|
@ -5,7 +5,6 @@ import { FormGroup, Switch } from "@patternfly/react-core";
|
|||
|
||||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const BooleanComponent = ({
|
||||
name,
|
||||
|
@ -26,7 +25,7 @@ export const BooleanComponent = ({
|
|||
}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
data-testid={name}
|
||||
defaultValue={defaultValue}
|
||||
control={control}
|
||||
|
|
|
@ -12,7 +12,6 @@ import type { ClientQuery } from "@keycloak/keycloak-admin-client/lib/resources/
|
|||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const ClientSelectComponent = ({
|
||||
name,
|
||||
|
@ -58,7 +57,7 @@ export const ClientSelectComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
defaultValue={defaultValue || ""}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
|
||||
import type { ComponentProps } from "./components";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const ListComponent = ({
|
||||
name,
|
||||
|
@ -32,7 +31,7 @@ export const ListComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
data-testid={name}
|
||||
defaultValue={defaultValue || ""}
|
||||
control={control}
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const MultiValuedListComponent = ({
|
||||
name,
|
||||
|
@ -32,7 +31,7 @@ export const MultiValuedListComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
control={control}
|
||||
defaultValue={defaultValue ? [defaultValue] : []}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -11,10 +11,9 @@ import {
|
|||
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import type { ComponentProps } from "./components";
|
||||
import type { MultiLine } from "../multi-line-input/MultiLineInput";
|
||||
import type { MultiLine } from "../multi-line-input/multi-line-convert";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { convertToHyphens } from "../../util";
|
||||
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
||||
|
||||
export const MultivaluedRoleComponent = ({
|
||||
|
@ -24,7 +23,7 @@ export const MultivaluedRoleComponent = ({
|
|||
}: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const fieldName = `config.${convertToHyphens(name!)}`;
|
||||
const fieldName = `config.${name}`;
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { control } = useFormContext();
|
||||
|
|
|
@ -5,7 +5,6 @@ import { FormGroup } from "@patternfly/react-core";
|
|||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const MultiValuedStringComponent = ({
|
||||
name,
|
||||
|
@ -23,7 +22,7 @@ export const MultiValuedStringComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<MultiLineInput
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
aria-label={name}
|
||||
addButtonLabel={t("addMultivaluedLabel", {
|
||||
fieldLabel: t(label!).toLowerCase(),
|
||||
|
|
|
@ -18,7 +18,6 @@ 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 { convertToHyphens } from "../../util";
|
||||
|
||||
export const RoleComponent = ({ name, label, helpText }: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
|
@ -34,7 +33,7 @@ export const RoleComponent = ({ name, label, helpText }: ComponentProps) => {
|
|||
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
|
||||
const [selectedRole, setSelectedRole] = useState<RoleRepresentation>();
|
||||
|
||||
const fieldName = `config.${convertToHyphens(name!)}`;
|
||||
const fieldName = `config.${name}`;
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
|
|
|
@ -6,7 +6,6 @@ import { CodeEditor, Language } from "@patternfly/react-code-editor";
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const ScriptComponent = ({
|
||||
name,
|
||||
|
@ -30,7 +29,7 @@ export const ScriptComponent = ({
|
|||
fieldId={name!}
|
||||
>
|
||||
<Controller
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
defaultValue={defaultValue}
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -5,7 +5,6 @@ import { FormGroup, TextInput } from "@patternfly/react-core";
|
|||
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { convertToHyphens } from "../../util";
|
||||
|
||||
export const StringComponent = ({
|
||||
name,
|
||||
|
@ -29,7 +28,7 @@ export const StringComponent = ({
|
|||
data-testid={name}
|
||||
ref={register()}
|
||||
type="text"
|
||||
name={`config.${convertToHyphens(name!)}`}
|
||||
name={`config.${name}`}
|
||||
defaultValue={defaultValue?.toString()}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -10,20 +10,6 @@ import {
|
|||
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export type MultiLine = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
export function convertToMultiline(fields: string[]): MultiLine[] {
|
||||
return (fields.length > 0 ? fields : [""]).map((field) => {
|
||||
return { value: field };
|
||||
});
|
||||
}
|
||||
|
||||
export function toValue(formValue: MultiLine[]): string[] {
|
||||
return formValue.map((field) => field.value);
|
||||
}
|
||||
|
||||
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
||||
name: string;
|
||||
addButtonLabel?: string;
|
||||
|
|
13
src/components/multi-line-input/multi-line-convert.ts
Normal file
13
src/components/multi-line-input/multi-line-convert.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
export type MultiLine = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
export function convertToMultiline(fields: string[]): MultiLine[] {
|
||||
return (fields.length > 0 ? fields : [""]).map((field) => {
|
||||
return { value: field };
|
||||
});
|
||||
}
|
||||
|
||||
export function toValue(formValue: MultiLine[]): string[] {
|
||||
return formValue.map((field) => field.value);
|
||||
}
|
|
@ -91,18 +91,17 @@ export default function AddMapper() {
|
|||
|
||||
const save = async (idpMapper: IdentityProviderMapperRepresentation) => {
|
||||
const attributes = JSON.stringify(idpMapper.config?.attributes ?? []);
|
||||
const config = convertFormValuesToObject({
|
||||
...idpMapper.config,
|
||||
attributes,
|
||||
});
|
||||
const mapper = convertFormValuesToObject(idpMapper);
|
||||
|
||||
if (id) {
|
||||
const updatedMapper = {
|
||||
...idpMapper,
|
||||
...mapper,
|
||||
config: {
|
||||
attributes,
|
||||
},
|
||||
identityProviderAlias: alias!,
|
||||
id: id,
|
||||
name: currentMapper?.name!,
|
||||
config,
|
||||
};
|
||||
try {
|
||||
await adminClient.identityProviders.updateMapper(
|
||||
|
@ -120,9 +119,11 @@ export default function AddMapper() {
|
|||
try {
|
||||
const createdMapper = await adminClient.identityProviders.createMapper({
|
||||
identityProviderMapper: {
|
||||
...idpMapper,
|
||||
...mapper,
|
||||
identityProviderAlias: alias,
|
||||
config,
|
||||
config: {
|
||||
attributes,
|
||||
},
|
||||
},
|
||||
alias: alias!,
|
||||
});
|
||||
|
@ -161,28 +162,8 @@ export default function AddMapper() {
|
|||
|
||||
const setupForm = (mapper: IdentityProviderMapperRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(mapper).map(([key, value]) => {
|
||||
if (key === "config") {
|
||||
if (mapper.config?.["are.attribute.values.regex"]) {
|
||||
form.setValue(
|
||||
"config.are-attribute-values-regex",
|
||||
mapper.config["are.attribute.values.regex"]
|
||||
);
|
||||
}
|
||||
|
||||
if (mapper.config?.attributes) {
|
||||
form.setValue("config.attributes", JSON.parse(value.attributes));
|
||||
}
|
||||
|
||||
if (mapper.config?.role) {
|
||||
form.setValue("config.role", value.role[0]);
|
||||
}
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(mapper, form.setValue);
|
||||
form.setValue("config.attributes", JSON.parse(mapper.config.attributes));
|
||||
};
|
||||
|
||||
const targetOptions = ["local", "brokerId", "brokerUsername"];
|
||||
|
@ -229,7 +210,6 @@ export default function AddMapper() {
|
|||
() => formValues.identityProviderMapper?.includes("user-attribute-mapper"),
|
||||
[formValues.identityProviderMapper]
|
||||
);
|
||||
|
||||
const toggleModal = () => {
|
||||
setRolesModalOpen(!rolesModalOpen);
|
||||
};
|
||||
|
@ -357,8 +337,8 @@ export default function AddMapper() {
|
|||
<Controller
|
||||
name={
|
||||
isOIDCAdvancedClaimToRole
|
||||
? "config.are-claim-values-regex"
|
||||
: "config.are-attribute-values-regex"
|
||||
? "config.are.claim.values.regex"
|
||||
: "config.are.attribute.values.regex"
|
||||
}
|
||||
control={control}
|
||||
defaultValue="false"
|
||||
|
@ -548,14 +528,14 @@ export default function AddMapper() {
|
|||
<TextInput
|
||||
ref={register()}
|
||||
type="text"
|
||||
defaultValue={currentMapper?.config["attribute-value"]}
|
||||
defaultValue={currentMapper?.config["attribute.value"]}
|
||||
data-testid={
|
||||
isHardcodedUserSessionAttribute
|
||||
? "user-session-attribute-value"
|
||||
: "user-attribute-value"
|
||||
}
|
||||
id="kc-user-session-attribute-value"
|
||||
name="config.attribute-value"
|
||||
name="config.attribute.value"
|
||||
validated={
|
||||
errors.name
|
||||
? ValidatedOptions.error
|
||||
|
@ -594,10 +574,10 @@ export default function AddMapper() {
|
|||
<TextInput
|
||||
ref={register()}
|
||||
type="text"
|
||||
defaultValue={currentMapper?.config["attribute-name"]}
|
||||
defaultValue={currentMapper?.config["attribute.name"]}
|
||||
id="kc-attribute-name"
|
||||
data-testid="attribute-name"
|
||||
name="config.attribute-name"
|
||||
name="config.attribute.name"
|
||||
validated={
|
||||
errors.name
|
||||
? ValidatedOptions.error
|
||||
|
@ -629,11 +609,11 @@ export default function AddMapper() {
|
|||
ref={register()}
|
||||
type="text"
|
||||
defaultValue={
|
||||
currentMapper?.config["attribute-friendly-name"]
|
||||
currentMapper?.config["attribute.friendly.name"]
|
||||
}
|
||||
data-testid="attribute-friendly-name"
|
||||
id="kc-attribute-friendly-name"
|
||||
name="config.attribute-friendly-name"
|
||||
name="config.attribute.friendly.name"
|
||||
validated={
|
||||
errors.name
|
||||
? ValidatedOptions.error
|
||||
|
@ -715,11 +695,11 @@ export default function AddMapper() {
|
|||
type="text"
|
||||
defaultValue={
|
||||
isOIDCclaimToRole
|
||||
? currentMapper?.config["claim-value"]
|
||||
: currentMapper?.config["attribute-value"]
|
||||
? currentMapper?.config["claim.value"]
|
||||
: currentMapper?.config["attribute.value"]
|
||||
}
|
||||
data-testid={
|
||||
isOIDCclaimToRole ? "claim-value" : "user-attribute-name"
|
||||
isOIDCclaimToRole ? "claim.value" : "user-attribute-name"
|
||||
}
|
||||
id={
|
||||
isOIDCclaimToRole
|
||||
|
@ -727,7 +707,7 @@ export default function AddMapper() {
|
|||
: "kc-user-attribute-name"
|
||||
}
|
||||
name={
|
||||
isOIDCclaimToRole ? "config.claim" : "config.user-attribute"
|
||||
isOIDCclaimToRole ? "config.claim" : "config.user.attribute"
|
||||
}
|
||||
validated={
|
||||
errors.name
|
||||
|
|
|
@ -77,12 +77,7 @@ export default function ExecutorForm() {
|
|||
);
|
||||
|
||||
if (profileExecutor) {
|
||||
Object.entries(profileExecutor).map(([key, value]) => {
|
||||
if (key === "configuration") {
|
||||
convertToFormValues(value, "config", setValue);
|
||||
}
|
||||
setValue(key, value);
|
||||
});
|
||||
convertToFormValues(profileExecutor, setValue);
|
||||
}
|
||||
},
|
||||
[]
|
||||
|
|
|
@ -33,7 +33,7 @@ import type { EditClientPolicyConditionParams } from "./routes/EditCondition";
|
|||
import {
|
||||
convertToMultiline,
|
||||
toValue,
|
||||
} from "../components/multi-line-input/MultiLineInput";
|
||||
} from "../components/multi-line-input/multi-line-convert";
|
||||
import {
|
||||
COMPONENTS,
|
||||
isValidComponentType,
|
||||
|
|
|
@ -49,7 +49,6 @@ import { toRealmSettings } from "./routes/RealmSettings";
|
|||
import { LocalizationTab } from "./LocalizationTab";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { UserRegistration } from "./UserRegistration";
|
||||
import { DEFAULT_LOCALE } from "../i18n";
|
||||
import { toDashboard } from "../dashboard/routes/Dashboard";
|
||||
import environment from "../environment";
|
||||
import { UserProfileTab } from "./UserProfileTab";
|
||||
|
@ -188,15 +187,7 @@ export const RealmSettingsTabs = ({
|
|||
};
|
||||
|
||||
const setupForm = (r: RealmRepresentation = realm) => {
|
||||
Object.entries(r).map(([key, value]) => {
|
||||
if (key === "attributes") {
|
||||
convertToFormValues(value, "attributes", setValue);
|
||||
} else if (key === "supportedLocales" && value?.length === 0) {
|
||||
setValue(key, [DEFAULT_LOCALE]);
|
||||
} else {
|
||||
setValue(key, value);
|
||||
}
|
||||
});
|
||||
convertToFormValues(r, setValue);
|
||||
resetForm(getValues());
|
||||
};
|
||||
|
||||
|
@ -206,18 +197,13 @@ export const RealmSettingsTabs = ({
|
|||
|
||||
const save = async (realm: RealmRepresentation) => {
|
||||
try {
|
||||
const attributes = Object.fromEntries(
|
||||
Object.entries(
|
||||
convertFormValuesToObject(realm.attributes, true)
|
||||
).filter(([, v]) => v !== "")
|
||||
);
|
||||
realm = convertFormValuesToObject(realm);
|
||||
|
||||
await adminClient.realms.update(
|
||||
{ realm: realmName },
|
||||
{
|
||||
...realm,
|
||||
id: realmName,
|
||||
attributes,
|
||||
}
|
||||
);
|
||||
setupForm(realm);
|
||||
|
|
|
@ -88,20 +88,7 @@ export const AESGeneratedForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.secretSize &&
|
||||
component.config.active
|
||||
) {
|
||||
form.setValue("config.secretSize", value.secretSize[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -88,20 +88,7 @@ export const ECDSAGeneratedForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.ecdsaEllipticCurveKey &&
|
||||
component.config.active
|
||||
) {
|
||||
form.setValue("config.secretSize", value.ecdsaEllipticCurveKey[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -90,23 +90,7 @@ export const HMACGeneratedForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.secretSize &&
|
||||
component.config.active &&
|
||||
component.config.algorithm
|
||||
) {
|
||||
form.setValue("config.secretSize", value.secretSize[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
form.setValue("config.algorithm", value.active[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -88,33 +88,7 @@ export const JavaKeystoreForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.secretSize &&
|
||||
component.config.active &&
|
||||
component.config.algorithm &&
|
||||
component.config.keystore &&
|
||||
component.config.keystorePassword &&
|
||||
component.config.keyAlias &&
|
||||
component.config.keyPassword
|
||||
) {
|
||||
form.setValue("config.secretSize", value.secretSize[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
form.setValue("config.algorithm", value.algorithm[0]);
|
||||
|
||||
form.setValue("config.keystore", value.keystore[0]);
|
||||
|
||||
form.setValue("config.keyAlias", value.keyAlias[0]);
|
||||
|
||||
form.setValue("config.keyPassword", value.keyPassword[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -90,23 +90,7 @@ export const RSAGeneratedForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.secretSize &&
|
||||
component.config.active &&
|
||||
component.config.algorithm
|
||||
) {
|
||||
form.setValue("config.secretSize", value.secretSize[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
form.setValue("config.algorithm", value.active[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -95,29 +95,7 @@ export const RSAForm = ({
|
|||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
form.reset();
|
||||
Object.entries(component).map(([key, value]) => {
|
||||
if (
|
||||
key === "config" &&
|
||||
component.config?.secretSize &&
|
||||
component.config.active &&
|
||||
component.config.algorithm &&
|
||||
component.config.privateKey &&
|
||||
component.config.certificate
|
||||
) {
|
||||
form.setValue("config.secretSize", value.secretSize[0]);
|
||||
|
||||
form.setValue("config.active", value.active[0]);
|
||||
|
||||
form.setValue("config.algorithm", value.algorithm[0]);
|
||||
|
||||
form.setValue("config.privateKey", value.privateKey[0]);
|
||||
|
||||
form.setValue("config.certificate", value.certificate[0]);
|
||||
|
||||
convertToFormValues(value, "config", form.setValue);
|
||||
}
|
||||
form.setValue(key, value);
|
||||
});
|
||||
convertToFormValues(component, form.setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
import { KerberosSettingsRequired } from "./kerberos/KerberosSettingsRequired";
|
||||
import { SettingsCache } from "./shared/SettingsCache";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { convertToFormValues } from "../util";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
@ -107,16 +106,7 @@ export default function UserFederationKerberosSettings() {
|
|||
);
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
form.setValue(
|
||||
"config.allowPasswordAuthentication",
|
||||
component.config?.allowPasswordAuthentication
|
||||
);
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", form.setValue);
|
||||
}
|
||||
form.setValue(entry[0], entry[1]);
|
||||
});
|
||||
form.reset({ ...component });
|
||||
};
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
|
|
|
@ -21,7 +21,6 @@ import { LdapSettingsConnection } from "./ldap/LdapSettingsConnection";
|
|||
import { LdapSettingsSearching } from "./ldap/LdapSettingsSearching";
|
||||
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { convertToFormValues } from "../util";
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
@ -220,22 +219,16 @@ export default function UserFederationLdapSettings() {
|
|||
);
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
form.reset({ ...component });
|
||||
form.setValue(
|
||||
"config.periodicChangedUsersSync",
|
||||
entry[1].changedSyncPeriod[0] !== "-1"
|
||||
component.config?.["changedSyncPeriod"][0] !== "-1"
|
||||
);
|
||||
|
||||
form.setValue(
|
||||
"config.periodicFullSync",
|
||||
entry[1].fullSyncPeriod[0] !== "-1"
|
||||
component.config?.["fullSyncPeriod"][0] !== "-1"
|
||||
);
|
||||
|
||||
convertToFormValues(entry[1], "config", form.setValue);
|
||||
}
|
||||
form.setValue(entry[0], entry[1]);
|
||||
});
|
||||
};
|
||||
|
||||
const removeImportedUsers = async () => {
|
||||
|
|
|
@ -71,21 +71,11 @@ export default function LdapMapperDetails() {
|
|||
);
|
||||
|
||||
const setupForm = (mapper: ComponentRepresentation) => {
|
||||
Object.entries(mapper).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", form.setValue);
|
||||
} else {
|
||||
form.setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
convertToFormValues(mapper, form.setValue);
|
||||
};
|
||||
|
||||
const save = async (mapper: ComponentRepresentation) => {
|
||||
let config = {};
|
||||
if (mapper.config !== undefined) {
|
||||
config = convertFormValuesToObject(mapper.config);
|
||||
}
|
||||
const map = { ...mapper, config };
|
||||
const map = convertFormValuesToObject(mapper);
|
||||
|
||||
try {
|
||||
if (mapperId) {
|
||||
|
|
|
@ -34,7 +34,7 @@ export const LdapMapperFullNameAttribute = ({
|
|||
defaultValue="cn"
|
||||
id="kc-full-name-attribute"
|
||||
data-testid="mapper-fullNameAttribute-fld"
|
||||
name="config.ldap-full-name-attribute[0]"
|
||||
name="config.ldap.full.name.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -51,7 +51,7 @@ export const LdapMapperFullNameAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.read-only"
|
||||
name="config.read.only"
|
||||
defaultValue={["true"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -79,7 +79,7 @@ export const LdapMapperFullNameAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.write-only"
|
||||
name="config.write.only"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -33,7 +33,7 @@ export const LdapMapperHardcodedAttribute = ({
|
|||
type="text"
|
||||
id="kc-user-model-attribute"
|
||||
data-testid="mapper-userModelAttributeName-fld"
|
||||
name="config.user-model-attribute[0]"
|
||||
name="config.user.model.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -54,7 +54,7 @@ export const LdapMapperHardcodedAttribute = ({
|
|||
type="text"
|
||||
id="kc-attribute-value"
|
||||
data-testid="mapper-attributeValue-fld"
|
||||
name="config.attribute-value[0]"
|
||||
name="config.attribute.value[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -33,7 +33,7 @@ export const LdapMapperHardcodedLdapAttribute = ({
|
|||
type="text"
|
||||
id="kc-ldap-attribute-name"
|
||||
data-testid="mapper-ldapAttributeName-fld"
|
||||
name="config.ldap-attribute-name[0]"
|
||||
name="config.ldap.attribute.name[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -54,7 +54,7 @@ export const LdapMapperHardcodedLdapAttribute = ({
|
|||
type="text"
|
||||
id="kc-ldap-attribute-value"
|
||||
data-testid="mapper-ldapAttributeValue-fld"
|
||||
name="config.ldap-attribute-value[0]"
|
||||
name="config.ldap.attribute.value[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
|
|
@ -12,7 +12,7 @@ export const LdapMapperMsadUserAccount = ({
|
|||
form,
|
||||
}: LdapMapperMsadUserAccountProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const { t: helpText } = useTranslation("user-federation-help");
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
|
@ -28,7 +28,7 @@ export const LdapMapperMsadUserAccount = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.ldap-password-policy-hints-enabled"
|
||||
name="config.ldap.password.policy.hints.enabled"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
|
|
@ -67,11 +67,11 @@ export const LdapMapperRoleGroup = ({
|
|||
if (mapperId === "new" && vendor === "ad") {
|
||||
form.setValue(
|
||||
isRole
|
||||
? "config.role-object-classes[0]"
|
||||
: "config.group-object-classes[0]",
|
||||
? "config.role.object.classes[0]"
|
||||
: "config.group.object.classes[0]",
|
||||
"group"
|
||||
);
|
||||
form.setValue("config.membership-user-ldap-attribute[0]", "cn");
|
||||
form.setValue("config.membership.user.ldap.attribute[0]", "cn");
|
||||
}
|
||||
} else if (id) {
|
||||
throw new Error(t("common:notFound"));
|
||||
|
@ -103,7 +103,7 @@ export const LdapMapperRoleGroup = ({
|
|||
type="text"
|
||||
id="kc-ldap-dn"
|
||||
data-testid="ldap-dn"
|
||||
name={isRole ? "config.roles-dn[0]" : "config.groups-dn[0]"}
|
||||
name={isRole ? "config.roles.dn[0]" : "config.groups.dn[0]"}
|
||||
ref={form.register({ required: true })}
|
||||
validated={
|
||||
isRole
|
||||
|
@ -144,8 +144,8 @@ export const LdapMapperRoleGroup = ({
|
|||
defaultValue="cn"
|
||||
name={
|
||||
isRole
|
||||
? "config.role-name-ldap-attribute[0]"
|
||||
: "config.group-name-ldap-attribute[0]"
|
||||
? "config.role.name.ldap.attribute[0]"
|
||||
: "config.group.name.ldap.attribute[0]"
|
||||
}
|
||||
ref={form.register}
|
||||
/>
|
||||
|
@ -174,8 +174,8 @@ export const LdapMapperRoleGroup = ({
|
|||
defaultValue="groupOfNames"
|
||||
name={
|
||||
isRole
|
||||
? "config.role-object-classes[0]"
|
||||
: "config.group-object-classes[0]"
|
||||
? "config.role.object.classes[0]"
|
||||
: "config.group.object.classes[0]"
|
||||
}
|
||||
ref={form.register}
|
||||
/>
|
||||
|
@ -195,7 +195,7 @@ export const LdapMapperRoleGroup = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.preserve-group-inheritance"
|
||||
name="config.preserve.group.inheritance"
|
||||
defaultValue={["true"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -223,7 +223,7 @@ export const LdapMapperRoleGroup = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.ignore-missing-groups"
|
||||
name="config.ignore.missing.groups"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -258,7 +258,7 @@ export const LdapMapperRoleGroup = ({
|
|||
defaultValue="member"
|
||||
id="kc-membership-ldap-attribute"
|
||||
data-testid="membership-ldap-attribute"
|
||||
name="config.membership-ldap-attribute[0]"
|
||||
name="config.membership.ldap.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -274,7 +274,7 @@ export const LdapMapperRoleGroup = ({
|
|||
fieldId="kc-membership-attribute-type"
|
||||
>
|
||||
<Controller
|
||||
name="config.membership-attribute-type[0]"
|
||||
name="config.membership.attribute.type[0]"
|
||||
defaultValue="DN"
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -319,7 +319,7 @@ export const LdapMapperRoleGroup = ({
|
|||
id="kc-membership-user-ldap-attribute"
|
||||
data-testid="membership-user-ldap-attribute"
|
||||
defaultValue="uid"
|
||||
name="config.membership-user-ldap-attribute[0]"
|
||||
name="config.membership.user.ldap.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -340,8 +340,8 @@ export const LdapMapperRoleGroup = ({
|
|||
data-testid="ldap-filter"
|
||||
name={
|
||||
isRole
|
||||
? "config.roles-ldap-filter[0]"
|
||||
: "config.groups-ldap-filter[0]"
|
||||
? "config.roles.ldap.filter[0]"
|
||||
: "config.groups.ldap.filter[0]"
|
||||
}
|
||||
ref={form.register}
|
||||
/>
|
||||
|
@ -399,7 +399,7 @@ export const LdapMapperRoleGroup = ({
|
|||
fieldId="kc-user-retrieve-strategy"
|
||||
>
|
||||
<Controller
|
||||
name="config.user-roles-retrieve-strategy[0]"
|
||||
name="config.user.roles.retrieve.strategy[0]"
|
||||
defaultValue="LOAD_ROLES_BY_MEMBER_ATTRIBUTE"
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -449,7 +449,7 @@ export const LdapMapperRoleGroup = ({
|
|||
fieldId="kc-user-retrieve-strategy"
|
||||
>
|
||||
<Controller
|
||||
name="config.user-roles-retrieve-strategy[0]"
|
||||
name="config.user.roles.retrieve.strategy[0]"
|
||||
defaultValue="LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -505,7 +505,7 @@ export const LdapMapperRoleGroup = ({
|
|||
id="kc-member-of-attribute"
|
||||
defaultValue="memberOf"
|
||||
data-testid="member-of-attribute"
|
||||
name="config.memberof-ldap-attribute[0]"
|
||||
name="config.memberof.ldap.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -524,7 +524,7 @@ export const LdapMapperRoleGroup = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.use-realm-roles-mapping"
|
||||
name="config.use.realm.roles.mapping"
|
||||
defaultValue={["true"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -551,7 +551,7 @@ export const LdapMapperRoleGroup = ({
|
|||
fieldId="kc-client-id"
|
||||
>
|
||||
<Controller
|
||||
name="config.client-id[0]"
|
||||
name="config.client.id[0]"
|
||||
defaultValue=""
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -596,7 +596,7 @@ export const LdapMapperRoleGroup = ({
|
|||
type="text"
|
||||
id="kc-mapped-attributes"
|
||||
data-testid="mapped-attributes"
|
||||
name="config.mapped-group-attributes[0]"
|
||||
name="config.mapped.group.attributes[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -613,7 +613,7 @@ export const LdapMapperRoleGroup = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.drop-non-existing-groups-during-sync"
|
||||
name="config.drop.non.existing.groups.during.sync"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -646,7 +646,7 @@ export const LdapMapperRoleGroup = ({
|
|||
id="kc-path"
|
||||
data-testid="path"
|
||||
defaultValue="/"
|
||||
name="config.groups-path[0]"
|
||||
name="config.groups.path[0]"
|
||||
ref={form.register({ required: true })}
|
||||
validated={
|
||||
form.errors.config?.["groups-path"]
|
||||
|
|
|
@ -35,7 +35,7 @@ export const LdapMapperUserAttribute = ({
|
|||
type="text"
|
||||
id="kc-user-model-attribute"
|
||||
data-testid="mapper-userModelAttribute-fld"
|
||||
name="config.user-model-attribute[0]"
|
||||
name="config.user.model.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -56,7 +56,7 @@ export const LdapMapperUserAttribute = ({
|
|||
type="text"
|
||||
id="kc-ldap-attribute"
|
||||
data-testid="mapper-ldapAttribute-fld"
|
||||
name="config.ldap-attribute[0]"
|
||||
name="config.ldap.attribute[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -73,7 +73,7 @@ export const LdapMapperUserAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.read-only"
|
||||
name="config.read.only"
|
||||
defaultValue={
|
||||
mapperType === "user-attribute-ldap-mapper" ? ["true"] : ["false"]
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ export const LdapMapperUserAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.always-read-value-from-ldap"
|
||||
name="config.always.read.value.from.ldap"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -131,7 +131,7 @@ export const LdapMapperUserAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.is-mandatory-in-ldap"
|
||||
name="config.is.mandatory.in.ldap"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -161,7 +161,7 @@ export const LdapMapperUserAttribute = ({
|
|||
type="text"
|
||||
id="kc-attribute-default-value"
|
||||
data-testid="mapper-attributeDefaultValue-fld"
|
||||
name="config.attribute-default-value[0]"
|
||||
name="config.attribute.default.value[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -178,7 +178,7 @@ export const LdapMapperUserAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.is-binary-attribute"
|
||||
name="config.is.binary.attribute"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
|
@ -207,12 +207,12 @@ export const LdapMapperUserAttribute = ({
|
|||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="config.is-der-formatted"
|
||||
name="config.is.der.formatted"
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-der-formatted"}
|
||||
id="kc-der-formatted"
|
||||
isDisabled={false}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
|
|
140
src/util.test.ts
Normal file
140
src/util.test.ts
Normal file
|
@ -0,0 +1,140 @@
|
|||
import { convertFormValuesToObject, convertToFormValues } from "./util";
|
||||
|
||||
jest.mock("react");
|
||||
|
||||
describe("Tests the form convert util functions", () => {
|
||||
it("convert to form values", () => {
|
||||
const given = {
|
||||
name: "client",
|
||||
other: { one: "1", two: "2" },
|
||||
attributes: { one: ["1"] },
|
||||
};
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues(given, spy);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
name: "client",
|
||||
other: { one: "1", two: "2" },
|
||||
attributes: [
|
||||
{ key: "one", value: "1" },
|
||||
{ key: "", value: "" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("convert save values", () => {
|
||||
const given = {
|
||||
name: "client",
|
||||
attributes: [{ key: "one", value: "1" }],
|
||||
config: { one: { two: "3" } },
|
||||
};
|
||||
|
||||
//when
|
||||
const values = convertFormValuesToObject(given);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
name: "client",
|
||||
attributes: { one: ["1"] },
|
||||
config: { "one.two": "3" },
|
||||
});
|
||||
});
|
||||
|
||||
it("convert attributes flatten", () => {
|
||||
const given = {
|
||||
name: "test",
|
||||
description: "",
|
||||
type: "default",
|
||||
attributes: {
|
||||
display: { on: { consent: { screen: "true" } } },
|
||||
include: { in: { token: { scope: "true" } } },
|
||||
gui: { order: "1" },
|
||||
consent: { screen: { text: "" } },
|
||||
},
|
||||
};
|
||||
|
||||
//when
|
||||
const values = convertFormValuesToObject(given);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
name: "test",
|
||||
description: "",
|
||||
type: "default",
|
||||
attributes: {
|
||||
"display.on.consent.screen": "true",
|
||||
"include.in.token.scope": "true",
|
||||
"gui.order": "1",
|
||||
"consent.screen.text": "",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("convert flatten attributes to object", () => {
|
||||
const given = {
|
||||
attributes: {
|
||||
"display.on.consent.screen": "true",
|
||||
"include.in.token.scope": "true",
|
||||
"gui.order": "1",
|
||||
"consent.screen.text": "",
|
||||
},
|
||||
};
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues(given, spy);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
attributes: {
|
||||
display: { on: { consent: { screen: "true" } } },
|
||||
include: { in: { token: { scope: "true" } } },
|
||||
gui: { order: "1" },
|
||||
consent: { screen: { text: "" } },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("convert arrays to form values", () => {
|
||||
const given = {
|
||||
name: "test",
|
||||
description: "",
|
||||
redirectUris: ["http://bla.nl", "http://test.nl/bla", "http://test.nl"],
|
||||
};
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues(given, spy, ["redirectUris"]);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
name: "test",
|
||||
description: "",
|
||||
redirectUris: [
|
||||
{ value: "http://bla.nl" },
|
||||
{ value: "http://test.nl/bla" },
|
||||
{ value: "http://test.nl" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("convert form values to object", () => {
|
||||
const given = {
|
||||
redirectUris: [{ value: "http://bla.nl" }, { value: "http://test.nl" }],
|
||||
};
|
||||
|
||||
//when
|
||||
const values = convertFormValuesToObject(given, ["redirectUris"]);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
redirectUris: ["http://bla.nl", "http://test.nl"],
|
||||
});
|
||||
});
|
||||
});
|
98
src/util.ts
98
src/util.ts
|
@ -1,10 +1,22 @@
|
|||
import type { IFormatter, IFormatterValueType } from "@patternfly/react-table";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import FileSaver from "file-saver";
|
||||
import _ from "lodash";
|
||||
import type { IFormatter, IFormatterValueType } from "@patternfly/react-table";
|
||||
import { unflatten, 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";
|
||||
import type KeycloakAdminClient from "@keycloak/keycloak-admin-client";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
arrayToAttributes,
|
||||
attributesToArray,
|
||||
KeyValueType,
|
||||
} from "./components/attribute-form/attribute-convert";
|
||||
import {
|
||||
convertToMultiline,
|
||||
toValue,
|
||||
} from "./components/multi-line-input/multi-line-convert";
|
||||
|
||||
export const sortProviders = (providers: {
|
||||
[index: string]: ProviderRepresentation;
|
||||
|
@ -34,7 +46,7 @@ const sortProvider = (
|
|||
};
|
||||
|
||||
export const exportClient = (client: ClientRepresentation): void => {
|
||||
const clientCopy = _.cloneDeep(client);
|
||||
const clientCopy = cloneDeep(client);
|
||||
delete clientCopy.id;
|
||||
|
||||
if (clientCopy.protocolMappers) {
|
||||
|
@ -54,49 +66,59 @@ export const exportClient = (client: ClientRepresentation): void => {
|
|||
export const toUpperCase = <T extends string>(name: T) =>
|
||||
(name.charAt(0).toUpperCase() + name.slice(1)) as Capitalize<T>;
|
||||
|
||||
export const convertToHyphens = (s: string) => {
|
||||
return s.replaceAll(".", "-");
|
||||
const isAttributesObject = (value: any) => {
|
||||
return (
|
||||
Object.values(value).filter(
|
||||
(value) => Array.isArray(value) && value.length === 1
|
||||
).length !== 0
|
||||
);
|
||||
};
|
||||
|
||||
const isAttributeArray = (value: any) => {
|
||||
if (!Array.isArray(value)) {
|
||||
return false;
|
||||
}
|
||||
return value.filter((e) => e.key && e.value).length !== 0;
|
||||
};
|
||||
|
||||
const isEmpty = (obj: any) => Object.keys(obj).length === 0;
|
||||
|
||||
export const convertToFormValues = (
|
||||
obj: any,
|
||||
prefix: string,
|
||||
setValue: (name: string, value: any) => void
|
||||
setValue: (name: string, value: any) => void,
|
||||
multiline?: string[]
|
||||
) => {
|
||||
return Object.keys(obj).map((key) => {
|
||||
const newKey = convertToHyphens(key);
|
||||
setValue(prefix + "." + newKey, obj[key]);
|
||||
});
|
||||
};
|
||||
|
||||
export const flatten = (
|
||||
obj: Record<string, any> | undefined,
|
||||
path = ""
|
||||
): {} => {
|
||||
if (!(obj instanceof Object)) return { [path.replace(/\.$/g, "")]: obj };
|
||||
|
||||
return Object.keys(obj).reduce((output, key) => {
|
||||
return obj instanceof Array
|
||||
? {
|
||||
...output,
|
||||
...flatten(obj[key as unknown as number], path + "[" + key + "]."),
|
||||
Object.entries(obj).map(([key, value]) => {
|
||||
if (key === "attributes" && isAttributesObject(value)) {
|
||||
setValue(key, attributesToArray(value as Record<string, string[]>));
|
||||
} else if (key === "config" || key === "attributes") {
|
||||
setValue(key, !isEmpty(value) ? unflatten(value) : undefined);
|
||||
} else if (multiline?.includes(key)) {
|
||||
setValue(key, convertToMultiline(value as string[]));
|
||||
} else {
|
||||
setValue(key, value);
|
||||
}
|
||||
: { ...output, ...flatten(obj[key], path + key + ".") };
|
||||
}, {});
|
||||
});
|
||||
};
|
||||
|
||||
export const convertFormValuesToObject = (
|
||||
obj: any,
|
||||
firstInstanceOnly?: boolean
|
||||
) => {
|
||||
const keyValues = Object.keys(obj).map((key) => {
|
||||
const newKey = firstInstanceOnly
|
||||
? key.replace(/-/, ".")
|
||||
: key.replace(/-/g, ".");
|
||||
return { [newKey]: obj[key] };
|
||||
export function convertFormValuesToObject<T>(
|
||||
obj: T,
|
||||
multiline: string[] | undefined = []
|
||||
): Omit<T, typeof multiline[number] | "attributes" | "config"> {
|
||||
const result: any = {};
|
||||
Object.entries(obj).map(([key, value]) => {
|
||||
if (isAttributeArray(value)) {
|
||||
result[key] = arrayToAttributes(value as KeyValueType[]);
|
||||
} else if (multiline.includes(key)) {
|
||||
result[key] = toValue(value);
|
||||
} else if (key === "config" || key === "attributes") {
|
||||
result[key] = flatten(value as Record<string, any>, { safe: true });
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
});
|
||||
return Object.assign({}, ...keyValues);
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export const emptyFormatter =
|
||||
(): IFormatter => (data?: IFormatterValueType) => {
|
||||
|
|
Loading…
Reference in a new issue