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