Add Save/Cancel buttons and logic to LDAP settings (#311)
* add save cancel and move all form logic to parent * rm obsolete convert days function * save working all fields * fix save on two fields and rm console msgs * add basic validation to empty fields * fix default value issues in cache * fix two fields default values * dropdown text and help fixes * add empty option for edit mode
This commit is contained in:
parent
71a41694d9
commit
5633101f42
11 changed files with 566 additions and 590 deletions
|
@ -1,7 +1,13 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
Button,
|
||||
Form,
|
||||
PageSection,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from "react";
|
||||
import { ScrollForm } from "../components/scroll-form/ScrollForm";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import { LdapSettingsAdvanced } from "./ldap/LdapSettingsAdvanced";
|
||||
import { LdapSettingsKerberosIntegration } from "./ldap/LdapSettingsKerberosIntegration";
|
||||
import { LdapSettingsCache } from "./ldap/LdapSettingsCache";
|
||||
|
@ -9,9 +15,55 @@ import { LdapSettingsSynchronization } from "./ldap/LdapSettingsSynchronization"
|
|||
import { LdapSettingsGeneral } from "./ldap/LdapSettingsGeneral";
|
||||
import { LdapSettingsConnection } from "./ldap/LdapSettingsConnection";
|
||||
import { LdapSettingsSearching } from "./ldap/LdapSettingsSearching";
|
||||
import { ScrollForm } from "../components/scroll-form/ScrollForm";
|
||||
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { convertToFormValues } from "../util";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const UserFederationLdapSettings = () => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const form = useForm<ComponentRepresentation>();
|
||||
const history = useHistory();
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useRealm();
|
||||
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { addAlert } = useAlerts();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const fetchedComponent = await adminClient.components.findOne({ id });
|
||||
if (fetchedComponent) {
|
||||
setupForm(fetchedComponent);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", form.setValue);
|
||||
} else {
|
||||
form.setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const save = async (component: ComponentRepresentation) => {
|
||||
try {
|
||||
await adminClient.components.update({ id }, component);
|
||||
setupForm(component as ComponentRepresentation);
|
||||
addAlert(t("saveSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addAlert(`${t("saveError")} '${error}'`, AlertVariant.danger);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -27,27 +79,27 @@ export const UserFederationLdapSettings = () => {
|
|||
t("advancedSettings"),
|
||||
]}
|
||||
>
|
||||
{/* General settings */}
|
||||
<LdapSettingsGeneral />
|
||||
|
||||
{/* Connection settings */}
|
||||
<LdapSettingsConnection />
|
||||
|
||||
{/* Searching and updating settings */}
|
||||
<LdapSettingsSearching />
|
||||
|
||||
{/* Synchronization settings */}
|
||||
<LdapSettingsSynchronization />
|
||||
|
||||
{/* Kerberos integration */}
|
||||
<LdapSettingsKerberosIntegration />
|
||||
|
||||
{/* Cache settings */}
|
||||
<LdapSettingsCache />
|
||||
|
||||
{/* Advanced settings */}
|
||||
<LdapSettingsAdvanced />
|
||||
<LdapSettingsGeneral form={form} />
|
||||
<LdapSettingsConnection form={form} />
|
||||
<LdapSettingsSearching form={form} />
|
||||
<LdapSettingsSynchronization form={form} />
|
||||
<LdapSettingsKerberosIntegration form={form} />
|
||||
<LdapSettingsCache form={form} />
|
||||
<LdapSettingsAdvanced form={form} />
|
||||
</ScrollForm>
|
||||
<Form onSubmit={form.handleSubmit(save)}>
|
||||
<ActionGroup>
|
||||
<Button variant="primary" type="submit">
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
onClick={() => history.push(`/${realm}/user-federation`)}
|
||||
>
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</Form>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -13,8 +13,12 @@ import { LdapSettingsKerberosIntegration } from "./ldap/LdapSettingsKerberosInte
|
|||
import { LdapSettingsCache } from "./ldap/LdapSettingsCache";
|
||||
import { LdapSettingsAdvanced } from "./ldap/LdapSettingsAdvanced";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const UserFederationLdapWizard = () => {
|
||||
const form = useForm<ComponentRepresentation>();
|
||||
const { t } = useTranslation("user-federation");
|
||||
|
||||
const steps = [
|
||||
|
@ -22,21 +26,33 @@ export const UserFederationLdapWizard = () => {
|
|||
name: t("requiredSettings"),
|
||||
id: "ldapRequiredSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsGeneral showSectionHeading showSectionDescription />
|
||||
<LdapSettingsGeneral
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("connectionAndAuthenticationSettings"),
|
||||
id: "ldapConnectionSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsConnection showSectionHeading showSectionDescription />
|
||||
<LdapSettingsConnection
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("ldapSearchingAndUpdatingSettings"),
|
||||
id: "ldapSearchingSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsSearching showSectionHeading showSectionDescription />
|
||||
<LdapSettingsSearching
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
@ -44,6 +60,7 @@ export const UserFederationLdapWizard = () => {
|
|||
id: "ldapSynchronizationSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsSynchronization
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
|
@ -54,6 +71,7 @@ export const UserFederationLdapWizard = () => {
|
|||
id: "ldapKerberosIntegrationSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsKerberosIntegration
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
|
@ -63,14 +81,22 @@ export const UserFederationLdapWizard = () => {
|
|||
name: t("cacheSettings"),
|
||||
id: "ldapCacheSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsCache showSectionHeading showSectionDescription />
|
||||
<LdapSettingsCache
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("advancedSettings"),
|
||||
id: "ldapAdvancedSettingsStep",
|
||||
component: (
|
||||
<LdapSettingsAdvanced showSectionHeading showSectionDescription />
|
||||
<LdapSettingsAdvanced
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
"ldapConnectionAndAuthorizationSettingsDescription": "This section contains options related to the configuration of the connection to the LDAP server. It also contains options related to authentication of the LDAP connection to the LDAP server.",
|
||||
"consoleDisplayConnectionUrlHelp": "Connection URL to your LDAP server",
|
||||
"enableStarttlsHelp": "Encrypts the connection to LDAP using STARTTLS, which will disable connection pooling",
|
||||
"enableStartTlsHelp": "Encrypts the connection to LDAP using STARTTLS, which will disable connection pooling",
|
||||
"useTruststoreSpiHelp": "Specifies whether LDAP connection will use the Truststore SPI with the truststore configured in standalone.xml/domain.sml. 'Always' means that it will always use it. 'Never' means that it will not use it. 'Only for ldaps' means that it will use it if your connection URL use ldaps. Note that even if standalone.xml/domain.xml is not configured, the default java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.",
|
||||
"connectionPoolingHelp": "Determines if Keycloak should use connection pooling for accessing LDAP server.",
|
||||
"connectionTimeoutHelp": "LDAP connection timeout in milliseconds",
|
||||
|
@ -30,10 +30,12 @@
|
|||
"paginationHelp": "Whether the LDAP server supports pagination",
|
||||
|
||||
"ldapSynchronizationSettingsDescription": "This section contains options related to synchronization of users from LDAP to the Keycloak database.",
|
||||
"importUsersHelp": "Import users",
|
||||
"importUsersHelp": "If true, LDAP users will be imported into the Keycloak DB and synced by the configured sync policies.",
|
||||
"batchSizeHelp": "Count of LDAP users to be imported from LDAP to Keycloak within a single transaction",
|
||||
"periodicFullSyncHelp": "Whether periodic full synchronization of LDAP users to Keycloak should be enabled or not",
|
||||
"fullSyncPeriodHelp": "Period for full synchronization in seconds",
|
||||
"periodicChangedUsersSyncHelp": "Whether periodic synchronization of changed or newly created LDAP users to Keycloak should be enabled or not",
|
||||
"changedUsersSyncHelp": "Period for synchronization of changed or newly created LDAP users in seconds",
|
||||
|
||||
"ldapKerberosSettingsDescription": "This section contains options useful for the Kerberos integration. This is used only when the LDAP server is used together with Kerberos/SPNEGO for user authentication.",
|
||||
"allowKerberosAuthenticationHelp": "Enable/disable HTTP authentication of users with SPNEGO/Kerberos tokens. The data about authenticated users will be provisioned from this LDAP server.",
|
||||
|
|
|
@ -1,49 +1,24 @@
|
|||
import { FormGroup, Switch } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsAdvancedProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsAdvanced = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsAdvancedProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const adminClient = useAdminClient();
|
||||
const { control, setValue } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -70,14 +45,14 @@ export const LdapSettingsAdvanced = ({
|
|||
>
|
||||
<Controller
|
||||
name="config.usePasswordModifyExtendedOp"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-enable-ldapv3-password"}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
/>
|
||||
|
@ -99,14 +74,14 @@ export const LdapSettingsAdvanced = ({
|
|||
>
|
||||
<Controller
|
||||
name="config.validatePasswordPolicy"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
defaultValue={"false"}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-validate-password-policy"}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
/>
|
||||
|
@ -128,14 +103,14 @@ export const LdapSettingsAdvanced = ({
|
|||
>
|
||||
<Controller
|
||||
name="config.trustEmail"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
defaultValue={"false"}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-trust-email"}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
/>
|
||||
|
|
|
@ -3,84 +3,30 @@ import {
|
|||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Text,
|
||||
TextContent,
|
||||
TextInput,
|
||||
Title,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, useWatch, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import _ from "lodash";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsCacheProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsCache = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsCacheProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { control, setValue, register } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const convertToDays = (num: string) => {
|
||||
switch (num) {
|
||||
case "1":
|
||||
return t("common:Sunday");
|
||||
case "2":
|
||||
return t("common:Monday");
|
||||
case "3":
|
||||
return t("common:Tuesday");
|
||||
case "4":
|
||||
return t("common:Wednesday");
|
||||
case "5":
|
||||
return t("common:Thursday");
|
||||
case "6":
|
||||
return t("common:Friday");
|
||||
case "7":
|
||||
return t("common:Saturday");
|
||||
default:
|
||||
return t("common:selectOne");
|
||||
}
|
||||
};
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
if (entry[1].evictionDay) {
|
||||
setValue(
|
||||
"config.evictionDay",
|
||||
convertToDays(entry[1].evictionDay[0])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const fetchedComponent = await adminClient.components.findOne({ id });
|
||||
if (fetchedComponent) {
|
||||
setupForm(fetchedComponent);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const [isCachePolicyDropdownOpen, setIsCachePolicyDropdownOpen] = useState(
|
||||
false
|
||||
);
|
||||
|
@ -89,6 +35,11 @@ export const LdapSettingsCache = ({
|
|||
false
|
||||
);
|
||||
|
||||
const cachePolicyType = useWatch({
|
||||
control: form.control,
|
||||
name: "config.cachePolicy",
|
||||
});
|
||||
|
||||
const [
|
||||
isEvictionMinuteDropdownOpen,
|
||||
setIsEvictionMinuteDropdownOpen,
|
||||
|
@ -98,18 +49,16 @@ export const LdapSettingsCache = ({
|
|||
false
|
||||
);
|
||||
|
||||
const hourOptions = [
|
||||
<SelectOption key={0} value={t("common:selectOne")} isPlaceholder />,
|
||||
];
|
||||
for (let index = 1; index <= 24; index++) {
|
||||
hourOptions.push(<SelectOption key={index + 1} value={index} />);
|
||||
const hourOptions = [<SelectOption key={0} value={[`${1}`]} isPlaceholder />];
|
||||
for (let index = 2; index <= 24; index++) {
|
||||
hourOptions.push(<SelectOption key={index - 1} value={[`${index}`]} />);
|
||||
}
|
||||
|
||||
const minuteOptions = [
|
||||
<SelectOption key={0} value={t("common:selectOne")} isPlaceholder />,
|
||||
<SelectOption key={0} value={[`${1}`]} isPlaceholder />,
|
||||
];
|
||||
for (let index = 1; index <= 60; index++) {
|
||||
minuteOptions.push(<SelectOption key={index + 1} value={index} />);
|
||||
for (let index = 2; index <= 60; index++) {
|
||||
minuteOptions.push(<SelectOption key={index - 1} value={[`${index}`]} />);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -121,8 +70,6 @@ export const LdapSettingsCache = ({
|
|||
showDescription={showSectionDescription}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Cache settings */}
|
||||
<FormAccess role="manage-realm" isHorizontal>
|
||||
<FormGroup
|
||||
label={t("cachePolicy")}
|
||||
|
@ -137,8 +84,8 @@ export const LdapSettingsCache = ({
|
|||
>
|
||||
<Controller
|
||||
name="config.cachePolicy"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
defaultValue={["DEFAULT"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-cache-policy"
|
||||
|
@ -154,159 +101,177 @@ export const LdapSettingsCache = ({
|
|||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption key={0} value="Choose..." isPlaceholder />
|
||||
<SelectOption key={1} value="DEFAULT" />
|
||||
<SelectOption key={2} value="EVICT_DAILY" />
|
||||
<SelectOption key={3} value="EVICT_WEEKLY" />
|
||||
<SelectOption key={4} value="MAX_LIFESPAN" />
|
||||
<SelectOption key={5} value="NO_CACHE" />
|
||||
<SelectOption key={0} value={["DEFAULT"]} isPlaceholder />
|
||||
<SelectOption key={1} value={["EVICT_DAILY"]} />
|
||||
<SelectOption key={2} value={["EVICT_WEEKLY"]} />
|
||||
<SelectOption key={3} value={["MAX_LIFESPAN"]} />
|
||||
<SelectOption key={4} value={["NO_CACHE"]} />
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
|
||||
{/* TODO: Field shows only if cache policy is EVICT_WEEKLY */}
|
||||
<FormGroup
|
||||
label={t("evictionDay")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionDayHelp")}
|
||||
forLabel={t("evictionDay")}
|
||||
forID="kc-eviction-day"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-eviction-day"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionDay"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-day"
|
||||
required
|
||||
onToggle={() =>
|
||||
setIsEvictionDayDropdownOpen(!isEvictionDayDropdownOpen)
|
||||
}
|
||||
isOpen={isEvictionDayDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionDayDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption
|
||||
key={0}
|
||||
value={t("common:selectOne")}
|
||||
isPlaceholder
|
||||
/>
|
||||
<SelectOption key={1} value={t("common:Sunday")} />
|
||||
<SelectOption key={2} value={t("common:Monday")} />
|
||||
<SelectOption key={3} value={t("common:Tuesday")} />
|
||||
<SelectOption key={4} value={t("common:Wednesday")} />
|
||||
<SelectOption key={5} value={t("common:Thursday")} />
|
||||
<SelectOption key={6} value={t("common:Friday")} />
|
||||
<SelectOption key={7} value={t("common:Saturday")} />
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
|
||||
{/* TODO: Field shows only if cache policy is EVICT_WEEKLY or EVICT_DAILY */}
|
||||
{/* TODO: Investigate whether this should be a number field instead of a dropdown/text field */}
|
||||
<FormGroup
|
||||
label={t("evictionHour")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionHourHelp")}
|
||||
forLabel={t("evictionHour")}
|
||||
forID="kc-eviction-hour"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-eviction-hour"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionHour"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-hour"
|
||||
onToggle={() =>
|
||||
setIsEvictionHourDropdownOpen(!isEvictionHourDropdownOpen)
|
||||
}
|
||||
isOpen={isEvictionHourDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionHourDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
{hourOptions}
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
|
||||
{/* TODO: Field shows only if cache policy is EVICT_WEEKLY or EVICT_DAILY */}
|
||||
{/* TODO: Investigate whether this should be a number field instead of a dropdown/text field */}
|
||||
<FormGroup
|
||||
label={t("evictionMinute")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionMinuteHelp")}
|
||||
forLabel={t("evictionMinute")}
|
||||
forID="kc-eviction-minute"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-eviction-minute"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionMinute"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-minute"
|
||||
onToggle={() =>
|
||||
setIsEvictionMinuteDropdownOpen(!isEvictionMinuteDropdownOpen)
|
||||
}
|
||||
isOpen={isEvictionMinuteDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionMinuteDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
{minuteOptions}
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
|
||||
{/* TODO: Field shows only if cache policy is MAX_LIFESPAN */}
|
||||
<FormGroup
|
||||
label={t("maxLifespan")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("maxLifespanHelp")}
|
||||
forLabel={t("maxLifespan")}
|
||||
forID="kc-max-lifespan"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-max-lifespan"
|
||||
>
|
||||
<TextInput
|
||||
{_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
|
||||
<FormGroup
|
||||
label={t("evictionDay")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionDayHelp")}
|
||||
forLabel={t("evictionDay")}
|
||||
forID="kc-eviction-day"
|
||||
/>
|
||||
}
|
||||
isRequired
|
||||
type="text"
|
||||
id="kc-max-lifespan"
|
||||
name="config.maxLifespan"
|
||||
ref={register}
|
||||
/>
|
||||
</FormGroup>
|
||||
fieldId="kc-eviction-day"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionDay"
|
||||
defaultValue={[t("common:Sunday")]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-day"
|
||||
required
|
||||
onToggle={() =>
|
||||
setIsEvictionDayDropdownOpen(!isEvictionDayDropdownOpen)
|
||||
}
|
||||
isOpen={isEvictionDayDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionDayDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption key={0} value={["1"]} isPlaceholder>
|
||||
{t("common:Sunday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={1} value={["2"]}>
|
||||
{t("common:Monday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={2} value={["3"]}>
|
||||
{t("common:Tuesday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={3} value={["4"]}>
|
||||
{t("common:Wednesday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={4} value={["5"]}>
|
||||
{t("common:Thursday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={5} value={["6"]}>
|
||||
{t("common:Friday")}
|
||||
</SelectOption>
|
||||
<SelectOption key={6} value={["7"]}>
|
||||
{t("common:Saturday")}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{_.isEqual(cachePolicyType, ["EVICT_DAILY"]) ||
|
||||
_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("evictionHour")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionHourHelp")}
|
||||
forLabel={t("evictionHour")}
|
||||
forID="kc-eviction-hour"
|
||||
/>
|
||||
}
|
||||
isRequired
|
||||
fieldId="kc-eviction-hour"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionHour"
|
||||
defaultValue={["1"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-hour"
|
||||
onToggle={() =>
|
||||
setIsEvictionHourDropdownOpen(!isEvictionHourDropdownOpen)
|
||||
}
|
||||
isOpen={isEvictionHourDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionHourDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
{hourOptions}
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("evictionMinute")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("evictionMinuteHelp")}
|
||||
forLabel={t("evictionMinute")}
|
||||
forID="kc-eviction-minute"
|
||||
/>
|
||||
}
|
||||
isRequired
|
||||
fieldId="kc-eviction-minute"
|
||||
>
|
||||
<Controller
|
||||
name="config.evictionMinute"
|
||||
defaultValue={["1"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-eviction-minute"
|
||||
onToggle={() =>
|
||||
setIsEvictionMinuteDropdownOpen(
|
||||
!isEvictionMinuteDropdownOpen
|
||||
)
|
||||
}
|
||||
isOpen={isEvictionMinuteDropdownOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setIsEvictionMinuteDropdownOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
{minuteOptions}
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{_.isEqual(cachePolicyType, ["MAX_LIFESPAN"]) ? (
|
||||
<FormGroup
|
||||
label={t("maxLifespan")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("maxLifespanHelp")}
|
||||
forLabel={t("maxLifespan")}
|
||||
forID="kc-max-lifespan"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-max-lifespan"
|
||||
>
|
||||
<TextInput
|
||||
isRequired
|
||||
type="text"
|
||||
id="kc-max-lifespan"
|
||||
name="config.maxLifespan[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</FormAccess>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -9,46 +9,26 @@ import {
|
|||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { Controller, UseFormMethods } from "react-hook-form";
|
||||
import { EyeIcon } from "@patternfly/react-icons";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsConnectionProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsConnection = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsConnectionProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const adminClient = useAdminClient();
|
||||
const { register, control, setValue } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const convertTruststoreSpiValues = (truststoreValue: string) => {
|
||||
switch (truststoreValue) {
|
||||
case "always":
|
||||
return `${t("always")}`;
|
||||
case "never":
|
||||
return `${t("never")}`;
|
||||
case "ldapsOnly":
|
||||
default:
|
||||
return `${t("onlyLdaps")}`;
|
||||
}
|
||||
};
|
||||
|
||||
const [
|
||||
isTruststoreSpiDropdownOpen,
|
||||
|
@ -57,29 +37,6 @@ export const LdapSettingsConnection = ({
|
|||
|
||||
const [isBindTypeDropdownOpen, setIsBindTypeDropdownOpen] = useState(false);
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
if (entry[1].useTruststoreSpi) {
|
||||
setValue(
|
||||
"config.useTruststoreSpi",
|
||||
convertTruststoreSpiValues(entry[1].useTruststoreSpi[0])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{showSectionHeading && (
|
||||
|
@ -91,7 +48,6 @@ export const LdapSettingsConnection = ({
|
|||
showDescription={showSectionDescription}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormAccess role="manage-realm" isHorizontal>
|
||||
<FormGroup
|
||||
label={t("connectionURL")}
|
||||
|
@ -109,9 +65,21 @@ export const LdapSettingsConnection = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-console-connection-url"
|
||||
name="config.connectionUrl"
|
||||
ref={register}
|
||||
name="config.connectionUrl[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateConnectionUrl")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.connectionUrl &&
|
||||
form.errors.config.connectionUrl[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.connectionUrl[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("enableStartTls")}
|
||||
|
@ -127,14 +95,14 @@ export const LdapSettingsConnection = ({
|
|||
>
|
||||
<Controller
|
||||
name="config.startTls"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
defaultValue={["false"]}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-enable-start-tls"}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
/>
|
||||
|
@ -154,9 +122,9 @@ export const LdapSettingsConnection = ({
|
|||
fieldId="kc-use-truststore-spi"
|
||||
>
|
||||
<Controller
|
||||
name="config.useTruststoreSpi"
|
||||
name="config.useTruststoreSpi[0]"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-use-truststore-spi"
|
||||
|
@ -171,9 +139,15 @@ export const LdapSettingsConnection = ({
|
|||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption key={0} value={t("always")} />
|
||||
<SelectOption key={1} value={t("onlyLdaps")} />
|
||||
<SelectOption key={2} value={t("never")} />
|
||||
<SelectOption key={0} value="always">
|
||||
{t("always")}
|
||||
</SelectOption>
|
||||
<SelectOption key={1} value="ldapsOnly">
|
||||
{t("onlyLdaps")}
|
||||
</SelectOption>
|
||||
<SelectOption key={2} value="never">
|
||||
{t("never")}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
|
@ -193,12 +167,12 @@ export const LdapSettingsConnection = ({
|
|||
<Controller
|
||||
name="config.connectionPooling"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-connection-pooling"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
|
@ -220,8 +194,8 @@ export const LdapSettingsConnection = ({
|
|||
<TextInput
|
||||
type="text"
|
||||
id="kc-console-connection-timeout"
|
||||
name="config.connectionTimeout"
|
||||
ref={register}
|
||||
name="config.connectionTimeout[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
|
@ -237,9 +211,9 @@ export const LdapSettingsConnection = ({
|
|||
isRequired
|
||||
>
|
||||
<Controller
|
||||
name="config.authType"
|
||||
name="config.authType[0]"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-bind-type"
|
||||
|
@ -275,8 +249,8 @@ export const LdapSettingsConnection = ({
|
|||
<TextInput
|
||||
type="text"
|
||||
id="kc-console-bind-dn"
|
||||
name="config.bindDn"
|
||||
ref={register}
|
||||
name="config.bindDn[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
|
@ -291,14 +265,18 @@ export const LdapSettingsConnection = ({
|
|||
fieldId="kc-console-bind-credentials"
|
||||
isRequired
|
||||
>
|
||||
{/* TODO: MF The input group below throws a 'React does not recognize the `isDisabled` prop on a DOM element' error */}
|
||||
<InputGroup>
|
||||
<TextInput // TODO: Make password field switch to type=text with button
|
||||
isRequired
|
||||
type="password"
|
||||
id="kc-console-bind-credentials"
|
||||
name="config.bindCredential"
|
||||
ref={register}
|
||||
name="config.bindCredential[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateBindCredentials")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
variant="control"
|
||||
|
@ -307,6 +285,13 @@ export const LdapSettingsConnection = ({
|
|||
<EyeIcon />
|
||||
</Button>
|
||||
</InputGroup>
|
||||
{form.errors.config &&
|
||||
form.errors.config.bindCredential &&
|
||||
form.errors.config.bindCredential[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.bindCredential[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup fieldId="kc-test-button">
|
||||
{" "}
|
||||
|
|
|
@ -3,78 +3,31 @@ import {
|
|||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Text,
|
||||
TextContent,
|
||||
TextInput,
|
||||
Title,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsGeneralProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsGeneral = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsGeneralProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const adminClient = useAdminClient();
|
||||
const { register, control, setValue } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const [isVendorDropdownOpen, setIsVendorDropdownOpen] = useState(false);
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
if (entry[1].vendor) {
|
||||
setValue("config.vendor", convertVendorNames(entry[1].vendor[0]));
|
||||
}
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
|
||||
const convertVendorNames = (vendorName: string) => {
|
||||
switch (vendorName) {
|
||||
case "ad":
|
||||
return "Active Directory";
|
||||
case "rhds":
|
||||
return "Red Hat Directory Server";
|
||||
case "tivoli":
|
||||
return "Tivoli";
|
||||
case "edirectory":
|
||||
return "Novell eDirectory";
|
||||
case "other":
|
||||
return "Other";
|
||||
default:
|
||||
return t("common:choose");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{showSectionHeading && (
|
||||
|
@ -84,7 +37,6 @@ export const LdapSettingsGeneral = ({
|
|||
showDescription={showSectionDescription}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormAccess role="manage-realm" isHorizontal>
|
||||
<FormGroup
|
||||
label={t("consoleDisplayName")}
|
||||
|
@ -98,13 +50,50 @@ export const LdapSettingsGeneral = ({
|
|||
fieldId="kc-console-display-name"
|
||||
isRequired
|
||||
>
|
||||
{/* These hidden fields are required so data object written back matches data retrieved */}
|
||||
<TextInput
|
||||
hidden
|
||||
type="text"
|
||||
id="kc-console-id"
|
||||
name="id"
|
||||
ref={form.register}
|
||||
/>
|
||||
<TextInput
|
||||
isRequired
|
||||
type="text"
|
||||
id="kc-console-display-name"
|
||||
name="name"
|
||||
ref={register}
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateName")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<TextInput
|
||||
hidden
|
||||
type="text"
|
||||
id="kc-console-provider-id"
|
||||
name="providerId"
|
||||
ref={form.register}
|
||||
/>
|
||||
<TextInput
|
||||
hidden
|
||||
type="text"
|
||||
id="kc-console-provider-type"
|
||||
name="providerType"
|
||||
ref={form.register}
|
||||
/>
|
||||
<TextInput
|
||||
hidden
|
||||
type="text"
|
||||
id="kc-console-parentId"
|
||||
name="parentId"
|
||||
ref={form.register}
|
||||
/>
|
||||
{form.errors.name && (
|
||||
<div className="error">{form.errors.name.message}</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("vendor")}
|
||||
|
@ -119,9 +108,9 @@ export const LdapSettingsGeneral = ({
|
|||
isRequired
|
||||
>
|
||||
<Controller
|
||||
name="config.vendor"
|
||||
name="config.vendor[0]"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-vendor"
|
||||
|
@ -135,16 +124,21 @@ export const LdapSettingsGeneral = ({
|
|||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption
|
||||
key={0}
|
||||
value={t("common:choose")}
|
||||
isPlaceholder
|
||||
/>
|
||||
<SelectOption key={1} value="Active Directory" />
|
||||
<SelectOption key={2} value="Red Hat Directory Server" />
|
||||
<SelectOption key={3} value="Tivoli" />
|
||||
<SelectOption key={4} value="Novell eDirectory" />
|
||||
<SelectOption key={5} value="Other" />
|
||||
<SelectOption key={0} value="ad" isPlaceholder>
|
||||
Active Directory
|
||||
</SelectOption>
|
||||
<SelectOption key={1} value="rhds">
|
||||
Red Hat Directory Server
|
||||
</SelectOption>
|
||||
<SelectOption key={2} value="tivoli">
|
||||
Tivoli
|
||||
</SelectOption>
|
||||
<SelectOption key={3} value="edirectory">
|
||||
Novell eDirectory
|
||||
</SelectOption>
|
||||
<SelectOption key={4} value="other">
|
||||
Other
|
||||
</SelectOption>
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
|
|
|
@ -1,51 +1,25 @@
|
|||
import { FormGroup, Switch } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsKerberosIntegrationProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsKerberosIntegration = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsKerberosIntegrationProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { control, setValue } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{showSectionHeading && (
|
||||
|
@ -72,12 +46,12 @@ export const LdapSettingsKerberosIntegration = ({
|
|||
<Controller
|
||||
name="config.allowKerberosAuthentication"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-allow-kerberos-authentication"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
|
@ -100,12 +74,12 @@ export const LdapSettingsKerberosIntegration = ({
|
|||
<Controller
|
||||
name="config.useKerberosForPasswordAuthentication"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-use-kerberos-password-authentication"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
|
|
|
@ -7,70 +7,30 @@ import {
|
|||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsSearchingProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsSearching = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsSearchingProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const adminClient = useAdminClient();
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const [isEditModeDropdownOpen, setIsEditModeDropdownOpen] = useState(false);
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const [isSearchScopeDropdownOpen, setIsSearchScopeDropdownOpen] = useState(
|
||||
false
|
||||
);
|
||||
const { register, control, setValue } = useForm<ComponentRepresentation>();
|
||||
|
||||
const convertSearchScopes = (scope: string) => {
|
||||
switch (scope) {
|
||||
case "1":
|
||||
default:
|
||||
return `${t("oneLevel")}`;
|
||||
case "2":
|
||||
return `${t("subtree")}`;
|
||||
}
|
||||
};
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
if (entry[1].searchScope) {
|
||||
setValue(
|
||||
"config.searchScope",
|
||||
convertSearchScopes(entry[1].searchScope[0])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
const [isEditModeDropdownOpen, setIsEditModeDropdownOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -95,9 +55,9 @@ export const LdapSettingsSearching = ({
|
|||
fieldId="kc-edit-mode"
|
||||
>
|
||||
<Controller
|
||||
name="config.editMode"
|
||||
name="config.editMode[0]"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-edit-mode"
|
||||
|
@ -113,12 +73,8 @@ export const LdapSettingsSearching = ({
|
|||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption
|
||||
key={0}
|
||||
value={t("common:choose")}
|
||||
isPlaceholder
|
||||
/>
|
||||
<SelectOption key={1} value="RACT_ONLY" />
|
||||
<SelectOption key={0} value="" isPlaceholder />
|
||||
<SelectOption key={1} value="READ_ONLY" />
|
||||
<SelectOption key={2} value="WRITABLE" />
|
||||
<SelectOption key={3} value="UNSYNCED" />
|
||||
</Select>
|
||||
|
@ -141,9 +97,21 @@ export const LdapSettingsSearching = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-console-users-dn"
|
||||
name="config.usersDn"
|
||||
ref={register}
|
||||
name="config.usersDn[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateUsersDn")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.usersDn &&
|
||||
form.errors.config.usersDn[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.usersDn[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("usernameLdapAttribute")}
|
||||
|
@ -161,9 +129,21 @@ export const LdapSettingsSearching = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-username-ldap-attribute"
|
||||
name="config.usernameLDAPAttribute"
|
||||
ref={register}
|
||||
name="config.usernameLDAPAttribute[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateUsernameLDAPAttribute")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.usernameLDAPAttribute &&
|
||||
form.errors.config.usernameLDAPAttribute[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.usernameLDAPAttribute[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("rdnLdapAttribute")}
|
||||
|
@ -181,9 +161,21 @@ export const LdapSettingsSearching = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-rdn-ldap-attribute"
|
||||
name="config.rdnLDAPAttribute"
|
||||
ref={register}
|
||||
name="config.rdnLDAPAttribute[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateRdnLdapAttribute")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.rdnLDAPAttribute &&
|
||||
form.errors.config.rdnLDAPAttribute[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.rdnLDAPAttribute[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("uuidLdapAttribute")}
|
||||
|
@ -201,9 +193,21 @@ export const LdapSettingsSearching = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-uuid-ldap-attribute"
|
||||
name="config.uuidLDAPAttribute"
|
||||
ref={register}
|
||||
name="config.uuidLDAPAttribute[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateUuidLDAPAttribute")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.uuidLDAPAttribute &&
|
||||
form.errors.config.uuidLDAPAttribute[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.uuidLDAPAttribute[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("userObjectClasses")}
|
||||
|
@ -221,9 +225,21 @@ export const LdapSettingsSearching = ({
|
|||
isRequired
|
||||
type="text"
|
||||
id="kc-user-object-classes"
|
||||
name="config.userObjectClasses"
|
||||
ref={register}
|
||||
name="config.userObjectClasses[0]"
|
||||
ref={form.register({
|
||||
required: {
|
||||
value: true,
|
||||
message: `${t("validateUserObjectClasses")}`,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{form.errors.config &&
|
||||
form.errors.config.userObjectClasses &&
|
||||
form.errors.config.userObjectClasses[0] && (
|
||||
<div className="error">
|
||||
{form.errors.config.userObjectClasses[0].message}
|
||||
</div>
|
||||
)}
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("userLdapFilter")}
|
||||
|
@ -239,10 +255,11 @@ export const LdapSettingsSearching = ({
|
|||
<TextInput
|
||||
type="text"
|
||||
id="kc-user-ldap-filter"
|
||||
name="config.customUserSearchFilter"
|
||||
ref={register}
|
||||
name="config.customUserSearchFilter[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
label={t("searchScope")}
|
||||
labelIcon={
|
||||
|
@ -255,9 +272,9 @@ export const LdapSettingsSearching = ({
|
|||
fieldId="kc-search-scope"
|
||||
>
|
||||
<Controller
|
||||
name="config.searchScope"
|
||||
name="config.searchScope[0]"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="kc-search-scope"
|
||||
|
@ -273,13 +290,12 @@ export const LdapSettingsSearching = ({
|
|||
selections={value}
|
||||
variant={SelectVariant.single}
|
||||
>
|
||||
<SelectOption
|
||||
key={0}
|
||||
value={t("common:choose")}
|
||||
isPlaceholder
|
||||
/>
|
||||
<SelectOption key={1} value={t("oneLevel")} />
|
||||
<SelectOption key={2} value={t("subtree")} />
|
||||
<SelectOption key={0} value="1" isPlaceholder>
|
||||
{t("oneLevel")}
|
||||
</SelectOption>
|
||||
<SelectOption key={1} value="2">
|
||||
{t("subtree")}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
)}
|
||||
></Controller>
|
||||
|
@ -298,8 +314,8 @@ export const LdapSettingsSearching = ({
|
|||
<TextInput
|
||||
type="text"
|
||||
id="kc-read-timeout"
|
||||
name="config.readTimeout"
|
||||
ref={register}
|
||||
name="config.readTimeout[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
|
@ -317,13 +333,13 @@ export const LdapSettingsSearching = ({
|
|||
<Controller
|
||||
name="config.pagination"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-console-pagination"}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
/>
|
||||
|
|
|
@ -1,49 +1,24 @@
|
|||
import { FormGroup, Switch, TextInput } from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { UseFormMethods, Controller } from "react-hook-form";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import {
|
||||
useAdminClient,
|
||||
asyncStateFetch,
|
||||
} from "../../context/auth/AdminClient";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
|
||||
export type LdapSettingsSynchronizationProps = {
|
||||
form: UseFormMethods;
|
||||
showSectionHeading?: boolean;
|
||||
showSectionDescription?: boolean;
|
||||
};
|
||||
|
||||
export const LdapSettingsSynchronization = ({
|
||||
form,
|
||||
showSectionHeading = false,
|
||||
showSectionDescription = false,
|
||||
}: LdapSettingsSynchronizationProps) => {
|
||||
const { t } = useTranslation("user-federation");
|
||||
const helpText = useTranslation("user-federation-help").t;
|
||||
const adminClient = useAdminClient();
|
||||
const { register, control, setValue } = useForm<ComponentRepresentation>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const setupForm = (component: ComponentRepresentation) => {
|
||||
Object.entries(component).map((entry) => {
|
||||
if (entry[0] === "config") {
|
||||
convertToFormValues(entry[1], "config", setValue);
|
||||
} else {
|
||||
setValue(entry[0], entry[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return asyncStateFetch(
|
||||
() => adminClient.components.findOne({ id }),
|
||||
(fetchedComponent) => setupForm(fetchedComponent)
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -54,7 +29,6 @@ export const LdapSettingsSynchronization = ({
|
|||
showDescription={showSectionDescription}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormAccess role="manage-realm" isHorizontal>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
|
@ -71,16 +45,16 @@ export const LdapSettingsSynchronization = ({
|
|||
<Controller
|
||||
name="config.importEnabled"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-import-users"}
|
||||
name="importEnabled"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
onChange={(value) => onChange([`${value}`])}
|
||||
isChecked={value[0] === "true"}
|
||||
isDisabled={false}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
></Controller>
|
||||
|
@ -99,46 +73,50 @@ export const LdapSettingsSynchronization = ({
|
|||
<TextInput
|
||||
type="text"
|
||||
id="kc-batch-size"
|
||||
name="config.batchSizeForSync"
|
||||
ref={register}
|
||||
name="config.batchSizeForSync[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{/* Enter -1 to switch off, otherwise enter value */}
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("periodicFullSync")}
|
||||
label={t("fullSyncPeriod")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("periodicFullSyncHelp")}
|
||||
forLabel={t("periodicFullSync")}
|
||||
forID="kc-periodic-full-sync"
|
||||
helpText={helpText("fullSyncPeriodHelp")}
|
||||
forLabel={t("fullSyncPeriod")}
|
||||
forID="kc-full-sync-period"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-periodic-full-sync"
|
||||
fieldId="kc-full-sync-period"
|
||||
>
|
||||
<TextInput
|
||||
type="text"
|
||||
id="kc-batch-size"
|
||||
name="config.fullSyncPeriod"
|
||||
ref={register}
|
||||
id="kc-full-sync-period"
|
||||
name="config.fullSyncPeriod[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{/* Enter -1 to switch off, otherwise enter value */}
|
||||
<FormGroup
|
||||
label={t("periodicChangedUsersSync")}
|
||||
label={t("changedUsersSyncPeriod")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={helpText("periodicChangedUsersSyncHelp")}
|
||||
forLabel={t("periodicChangedUsersSync")}
|
||||
forID="kc-periodic-changed-users-sync"
|
||||
helpText={helpText("changedUsersSyncHelp")}
|
||||
forLabel={t("changedUsersSyncPeriod")}
|
||||
forID="kc-changed-users-sync-period"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-periodic-changed-users-sync"
|
||||
fieldId="kc-changed-users-sync-period"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<TextInput
|
||||
type="text"
|
||||
id="kc-batch-size"
|
||||
name="config.changedSyncPeriod"
|
||||
ref={register}
|
||||
id="kc-changed-users-sync-period"
|
||||
name="config.changedSyncPeriod[0]"
|
||||
ref={form.register}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
"importUsers": "Import users",
|
||||
"batchSize": "Batch size",
|
||||
"periodicFullSync": "Periodic full sync",
|
||||
"fullSyncPeriod": "Full sync period",
|
||||
"periodicChangedUsersSync": "Periodic changed users sync",
|
||||
"changedUsersSyncPeriod": "Changed users sync period",
|
||||
|
||||
"kerberosIntegration": "Kerberos integration",
|
||||
"allowKerberosAuthentication": "Allow Kerberos authentication",
|
||||
|
@ -92,6 +94,13 @@
|
|||
"validateRealm":"You must enter a realm",
|
||||
"validateServerPrincipal":"You must enter a server principal",
|
||||
"validateKeyTab": "You must enter a key tab",
|
||||
"validateConnectionUrl": "You must enter a connection URL",
|
||||
"validateBindCredentials": "You must enter bind credentials",
|
||||
"validateUuidLDAPAttribute": "You must enter a UUID LDAP attribute",
|
||||
"validateUserObjectClasses": "You must enter one or more user object classes",
|
||||
"validateUsersDn": "You must enter users DN",
|
||||
"validateUsernameLDAPAttribute": "You must enter a username LDAP attribute",
|
||||
"validateRdnLdapAttribute": "You must enter an RDN LDAP attribute",
|
||||
|
||||
"id": "ID",
|
||||
"mapperType": "Mapper type",
|
||||
|
|
Loading…
Reference in a new issue