User Federation: populate all LDAP settings (#261)

* separate card paths

* organize settings file structure

* most ldap fields working

* allow same path to multiple components

* fix several fields

* all values fetched correctly

* changes from PR
This commit is contained in:
mfrances17 2020-12-16 02:02:41 -05:00 committed by GitHub
parent 0a5efbb781
commit 7c3a5739eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 428 additions and 216 deletions

View file

@ -27,6 +27,7 @@
"disabled": "Disabled",
"disable": "Disable",
"selectOne": "Select an option",
"choose": "Choose...",
"signOut": "Sign out",
"manageAccount": "Manage account",
"serverInfo": "Server info",

View file

@ -28,11 +28,12 @@ export type KeycloakCardProps = {
export const KeycloakCard = ({
id,
dropdownItems,
title,
dropdownItems,
labelText,
labelColor,
footerText,
providerId,
}: KeycloakCardProps) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@ -47,7 +48,11 @@ export const KeycloakCard = ({
};
const openSettings = () => {
history.push(`/user-federation/${id}`);
if (providerId === "kerberos") {
history.push(`/user-federation/Kerberos/${id}`);
} else {
history.push(`/user-federation/LDAP/${id}`);
}
};
return (

View file

@ -21,6 +21,7 @@ import { UsersSection } from "./user/UsersSection";
import { MappingDetails } from "./client-scopes/details/MappingDetails";
import { ClientDetails } from "./clients/ClientDetails";
import { UserFederationKerberosSettings } from "./user-federation/UserFederationKerberosSettings";
import { UserFederationLdapSettings } from "./user-federation/UserFederationLdapSettings";
import { RoleMappingForm } from "./client-scopes/add/RoleMappingForm";
export type RouteDef = {
@ -32,7 +33,7 @@ export type RouteDef = {
type RoutesFn = (t: TFunction) => RouteDef[];
export const routes: RoutesFn = (t: TFunction) => [
export const routes: RoutesFn = (t: any) => [
{
path: "/add-realm",
component: NewRealmForm,
@ -166,11 +167,29 @@ export const routes: RoutesFn = (t: TFunction) => [
access: "view-realm",
},
{
path: "/user-federation/:id",
path: "/user-federation/kerberos",
component: UserFederationSection,
breadcrumb: null,
access: "view-realm",
},
{
path: "/user-federation/ldap",
component: UserFederationSection,
breadcrumb: null,
access: "view-realm",
},
{
path: "/user-federation/kerberos/:id",
component: UserFederationKerberosSettings,
breadcrumb: t("common:settings"),
access: "view-realm",
},
{
path: "/user-federation/ldap/:id",
component: UserFederationLdapSettings,
breadcrumb: t("common:settings"),
access: "view-realm",
},
{
path: "/",
component: ClientsSection,

View file

@ -1,17 +1,17 @@
import React from "react";
import { Meta } from "@storybook/react";
import { Page } from "@patternfly/react-core";
import { UserFederationLdapSettingsTab } from "../user-federation/UserFederationLdapSettingsTab";
import { UserFederationLdapSettings } from "../user-federation/UserFederationLdapSettings";
export default {
title: "User Federation LDAP Settings Tab",
component: UserFederationLdapSettingsTab,
component: UserFederationLdapSettings,
} as Meta;
export const view = () => {
return (
<Page>
<UserFederationLdapSettingsTab />
<UserFederationLdapSettings />
</Page>
);
};

View file

@ -1,8 +1,8 @@
import { PageSection, Title } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React from "react";
import { KerberosSettingsRequired } from "./KerberosSettingsRequired";
import { KerberosSettingsCache } from "./KerberosSettingsCache";
import { KerberosSettingsRequired } from "./kerberos/KerberosSettingsRequired";
import { KerberosSettingsCache } from "./kerberos/KerberosSettingsCache";
export const UserFederationKerberosSettings = () => {
const { t } = useTranslation("user-federation");

View file

@ -2,15 +2,15 @@ import { PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React from "react";
import { ScrollForm } from "../components/scroll-form/ScrollForm";
import { LdapSettingsAdvanced } from "./LdapSettingsAdvanced";
import { LdapSettingsKerberosIntegration } from "./LdapSettingsKerberosIntegration";
import { LdapSettingsCache } from "./LdapSettingsCache";
import { LdapSettingsSynchronization } from "./LdapSettingsSynchronization";
import { LdapSettingsGeneral } from "./LdapSettingsGeneral";
import { LdapSettingsConnection } from "./LdapSettingsConnection";
import { LdapSettingsSearching } from "./LdapSettingsSearching";
import { LdapSettingsAdvanced } from "./ldap/LdapSettingsAdvanced";
import { LdapSettingsKerberosIntegration } from "./ldap/LdapSettingsKerberosIntegration";
import { LdapSettingsCache } from "./ldap/LdapSettingsCache";
import { LdapSettingsSynchronization } from "./ldap/LdapSettingsSynchronization";
import { LdapSettingsGeneral } from "./ldap/LdapSettingsGeneral";
import { LdapSettingsConnection } from "./ldap/LdapSettingsConnection";
import { LdapSettingsSearching } from "./ldap/LdapSettingsSearching";
export const UserFederationLdapSettingsTab = () => {
export const UserFederationLdapSettings = () => {
const { t } = useTranslation("user-federation");
return (

View file

@ -103,6 +103,7 @@ export const UserFederationSection = () => {
<KeycloakCard
id={userFederation.id!}
dropdownItems={ufCardDropdownItems}
providerId={userFederation.providerId!}
title={userFederation.name!}
footerText={
userFederation.providerId === "ldap" ? "LDAP" : "Kerberos"

View file

@ -6,13 +6,13 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import { HelpItem } from "../components/help-enabler/HelpItem";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import React, { useEffect, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { convertToFormValues } from "../util";
import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../components/form-access/FormAccess";
import { useAdminClient } from "../context/auth/AdminClient";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const KerberosSettingsCache = () => {
@ -48,7 +48,12 @@ export const KerberosSettingsCache = () => {
Object.entries(component).map((entry) => {
if (entry[0] === "config") {
convertToFormValues(entry[1], "config", setValue);
setValue("config.evictionDay", convertToDays(entry[1].evictionDay[0]));
if (entry[1].evictionDay) {
setValue(
"config.evictionDay",
convertToDays(entry[1].evictionDay[0])
);
}
} else {
setValue(entry[0], entry[1]);
}

View file

@ -8,13 +8,13 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import { HelpItem } from "../components/help-enabler/HelpItem";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useForm, Controller } from "react-hook-form";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../components/form-access/FormAccess";
import { useAdminClient } from "../context/auth/AdminClient";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
import { convertToFormValues } from "../util";
import { convertToFormValues } from "../../util";
export const KerberosSettingsRequired = () => {
const { t } = useTranslation("user-federation");
@ -28,9 +28,8 @@ export const KerberosSettingsRequired = () => {
Object.entries(component).map((entry) => {
if (entry[0] === "config") {
convertToFormValues(entry[1], "config", setValue);
} else {
setValue(entry[0], entry[1]);
}
setValue(entry[0], entry[1]);
});
};
@ -153,7 +152,7 @@ export const KerberosSettingsRequired = () => {
id={"kc-debug"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>
@ -182,7 +181,7 @@ export const KerberosSettingsRequired = () => {
id={"kc-allow-password-authentication"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>
@ -255,7 +254,7 @@ export const KerberosSettingsRequired = () => {
id={"kc-update-first-login"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>

View file

@ -1,16 +1,39 @@
import { FormGroup, Switch } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect } 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsAdvanced = () => {
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 { control } = useForm<ComponentRepresentation>();
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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
}, []);
return (
<>
@ -28,13 +51,13 @@ export const LdapSettingsAdvanced = () => {
hasNoPaddingTop
>
<Controller
name="enableLadpv3PasswordModify"
name="config.usePasswordModifyExtendedOp"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-enable-ldapv3-password"}
isChecked={value}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
label={t("common:on")}
@ -57,13 +80,13 @@ export const LdapSettingsAdvanced = () => {
hasNoPaddingTop
>
<Controller
name="validatePasswordPolicy"
name="config.validatePasswordPolicy"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-validate-password-policy"}
isChecked={value}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
label={t("common:on")}
@ -86,13 +109,13 @@ export const LdapSettingsAdvanced = () => {
hasNoPaddingTop
>
<Controller
name="trustEmail"
name="config.trustEmail"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-trust-email"}
isChecked={value}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
label={t("common:on")}

View file

@ -6,16 +6,69 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React, { useState } from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect, 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsCache = () => {
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
);
@ -23,6 +76,7 @@ export const LdapSettingsCache = () => {
const [isEvictionHourDropdownOpen, setIsEvictionHourDropdownOpen] = useState(
false
);
const [
isEvictionMinuteDropdownOpen,
setIsEvictionMinuteDropdownOpen,
@ -46,8 +100,6 @@ export const LdapSettingsCache = () => {
minuteOptions.push(<SelectOption key={index + 1} value={index} />);
}
const { control, register } = useForm<ComponentRepresentation>();
return (
<>
{/* Cache settings */}
@ -64,7 +116,7 @@ export const LdapSettingsCache = () => {
fieldId="kc-cache-policy"
>
<Controller
name="cachePolicy"
name="config.cachePolicy"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -81,8 +133,6 @@ export const LdapSettingsCache = () => {
}}
selections={value}
variant={SelectVariant.single}
// aria-label="Other"
// isDisabled
>
<SelectOption key={0} value="Choose..." isPlaceholder />
<SelectOption key={1} value="DEFAULT" />
@ -108,7 +158,7 @@ export const LdapSettingsCache = () => {
fieldId="kc-eviction-day"
>
<Controller
name="evictionDay"
name="config.evictionDay"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -157,7 +207,7 @@ export const LdapSettingsCache = () => {
fieldId="kc-eviction-hour"
>
<Controller
name="evictionHour"
name="config.evictionHour"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -194,7 +244,7 @@ export const LdapSettingsCache = () => {
fieldId="kc-eviction-minute"
>
<Controller
name="evictionMinute"
name="config.evictionMinute"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -233,7 +283,7 @@ export const LdapSettingsCache = () => {
isRequired
type="text"
id="kc-max-lifespan"
name="maxLifespan"
name="config.maxLifespan"
ref={register}
/>
</FormGroup>

View file

@ -9,16 +9,34 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React, { useState } from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect, 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 { EyeIcon } from "@patternfly/react-icons";
import { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsConnection = () => {
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,
@ -27,11 +45,33 @@ export const LdapSettingsConnection = () => {
const [isBindTypeDropdownOpen, setIsBindTypeDropdownOpen] = useState(false);
const { register, control } = useForm<ComponentRepresentation>();
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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
}, []);
return (
<>
{/* Cache settings */}
<FormAccess role="manage-realm" isHorizontal>
<FormGroup
label={t("connectionURL")}
@ -49,11 +89,10 @@ export const LdapSettingsConnection = () => {
isRequired
type="text"
id="kc-console-connection-url"
name="connectionUrl"
name="config.connectionUrl"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("enableStartTls")}
labelIcon={
@ -67,13 +106,13 @@ export const LdapSettingsConnection = () => {
hasNoPaddingTop
>
<Controller
name="enableStartTls"
name="config.startTls"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-enable-start-tls"}
isChecked={value}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
label={t("common:on")}
@ -95,7 +134,7 @@ export const LdapSettingsConnection = () => {
fieldId="kc-use-truststore-spi"
>
<Controller
name="useTruststoreSpi"
name="config.useTruststoreSpi"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -112,17 +151,13 @@ export const LdapSettingsConnection = () => {
selections={value}
variant={SelectVariant.single}
>
<SelectOption
key={0}
value="LDAP connection URL"
isPlaceholder
/>
<SelectOption key={1} value="something else" />
<SelectOption key={0} value={t("always")} />
<SelectOption key={1} value={t("onlyLdaps")} />
<SelectOption key={2} value={t("never")} />
</Select>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("connectionPooling")}
labelIcon={
@ -136,7 +171,7 @@ export const LdapSettingsConnection = () => {
hasNoPaddingTop
>
<Controller
name="connectionPooling"
name="config.connectionPooling"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
@ -144,14 +179,13 @@ export const LdapSettingsConnection = () => {
id={"kc-connection-pooling"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("connectionTimeout")}
labelIcon={
@ -166,11 +200,10 @@ export const LdapSettingsConnection = () => {
<TextInput
type="text"
id="kc-console-connection-timeout"
name="connectionTimeout"
name="config.connectionTimeout"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("bindType")}
labelIcon={
@ -184,7 +217,7 @@ export const LdapSettingsConnection = () => {
isRequired
>
<Controller
name="bindType"
name="config.authType"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -201,19 +234,13 @@ export const LdapSettingsConnection = () => {
}}
selections={value}
variant={SelectVariant.single}
// aria-label="simple" // TODO
>
<SelectOption
key={3}
value="Connection timeout"
isPlaceholder
/>
<SelectOption key={4} value="something" />
<SelectOption key={3} value="simple" />
<SelectOption key={4} value="none" />
</Select>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("bindDn")}
labelIcon={
@ -228,11 +255,10 @@ export const LdapSettingsConnection = () => {
<TextInput
type="text"
id="kc-console-bind-dn"
name="bindDn"
name="config.bindDn"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("bindCredentials")}
labelIcon={
@ -245,12 +271,13 @@ 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="bindCredentials"
name="config.bindCredential"
ref={register}
/>
<Button
@ -261,7 +288,6 @@ export const LdapSettingsConnection = () => {
</Button>
</InputGroup>
</FormGroup>
<FormGroup fieldId="kc-test-button">
{" "}
{/* TODO: whatever this button is supposed to do */}

View file

@ -6,23 +6,64 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React, { useState } from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect, 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsGeneral = () => {
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 { register, control } = useForm<ComponentRepresentation>();
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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (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 (
<>
{/* Cache settings */}
<FormAccess role="manage-realm" isHorizontal>
<FormGroup
label={t("consoleDisplayName")}
@ -40,11 +81,10 @@ export const LdapSettingsGeneral = () => {
isRequired
type="text"
id="kc-console-display-name"
name="displayName"
name="name"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("vendor")}
labelIcon={
@ -58,7 +98,7 @@ export const LdapSettingsGeneral = () => {
isRequired
>
<Controller
name="vendor"
name="config.vendor"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -73,10 +113,12 @@ export const LdapSettingsGeneral = () => {
}}
selections={value}
variant={SelectVariant.single}
// aria-label="Other"
// isDisabled
>
<SelectOption key={0} value="Choose..." isPlaceholder />
<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" />

View file

@ -1,20 +1,43 @@
import { FormGroup, Switch } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect } 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsKerberosIntegration = () => {
const { t } = useTranslation("user-federation");
const helpText = useTranslation("user-federation-help").t;
const { control } = useForm<ComponentRepresentation>();
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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
}, []);
return (
<>
{/* Kerberos integration */}
<FormAccess role="manage-realm" isHorizontal>
<FormGroup
label={t("allowKerberosAuthentication")}
@ -29,7 +52,7 @@ export const LdapSettingsKerberosIntegration = () => {
hasNoPaddingTop
>
<Controller
name="allowKerberosAuthentication"
name="config.allowKerberosAuthentication"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
@ -37,14 +60,13 @@ export const LdapSettingsKerberosIntegration = () => {
id={"kc-allow-kerberos-authentication"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("useKerberosForPasswordAuthentication")}
labelIcon={
@ -58,7 +80,7 @@ export const LdapSettingsKerberosIntegration = () => {
hasNoPaddingTop
>
<Controller
name="useKerberosForPasswordAuthentication"
name="config.useKerberosForPasswordAuthentication"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
@ -66,7 +88,7 @@ export const LdapSettingsKerberosIntegration = () => {
id={"kc-use-kerberos-password-authentication"}
isDisabled={false}
onChange={onChange}
isChecked={value}
isChecked={value[0] === "true"}
label={t("common:on")}
labelOff={t("common:off")}
/>

View file

@ -7,32 +7,63 @@ import {
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React, { useState } from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect, 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
import { convertToFormValues } from "../../util";
export const LdapSettingsSearching = () => {
const { t } = useTranslation("user-federation");
const adminClient = useAdminClient();
const helpText = useTranslation("user-federation-help").t;
const [isEditModeDropdownOpen, setIsEditModeDropdownOpen] = useState(false);
const [
isUserLdapFilterModeDropdownOpen,
setIsUserLdapFilterModeDropdownOpen,
] = useState(false);
const { id } = useParams<{ id: string }>();
const [isSearchScopeDropdownOpen, setIsSearchScopeDropdownOpen] = useState(
false
);
const { register, control, setValue } = useForm<ComponentRepresentation>();
const { register, control } = 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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
}, []);
return (
<>
{/* Cache settings */}
<FormAccess role="manage-realm" isHorizontal>
<FormGroup
label={t("editMode")}
@ -46,7 +77,7 @@ export const LdapSettingsSearching = () => {
fieldId="kc-edit-mode"
>
<Controller
name="editMode"
name="config.editMode"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -63,10 +94,12 @@ export const LdapSettingsSearching = () => {
}}
selections={value}
variant={SelectVariant.single}
// aria-label="Other"
// isDisabled
>
<SelectOption key={0} value="Choose..." isPlaceholder />
<SelectOption
key={0}
value={t("common:choose")}
isPlaceholder
/>
<SelectOption key={1} value="RACT_ONLY" />
<SelectOption key={2} value="WRITABLE" />
<SelectOption key={3} value="UNSYNCED" />
@ -74,7 +107,6 @@ export const LdapSettingsSearching = () => {
)}
></Controller>
</FormGroup>
<FormGroup
label={t("usersDN")}
labelIcon={
@ -91,11 +123,10 @@ export const LdapSettingsSearching = () => {
isRequired
type="text"
id="kc-console-users-dn"
name="usersDn"
name="config.usersDn"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("usernameLdapAttribute")}
labelIcon={
@ -112,11 +143,10 @@ export const LdapSettingsSearching = () => {
isRequired
type="text"
id="kc-username-ldap-attribute"
name="usernameLdapAttribute"
name="config.usernameLDAPAttribute"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("rdnLdapAttribute")}
labelIcon={
@ -133,11 +163,10 @@ export const LdapSettingsSearching = () => {
isRequired
type="text"
id="kc-rdn-ldap-attribute"
name="rdnLdapAttribute"
name="config.rdnLDAPAttribute"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("uuidLdapAttribute")}
labelIcon={
@ -154,11 +183,10 @@ export const LdapSettingsSearching = () => {
isRequired
type="text"
id="kc-uuid-ldap-attribute"
name="uuidLdapAttribute"
name="config.uuidLDAPAttribute"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("userObjectClasses")}
labelIcon={
@ -175,11 +203,10 @@ export const LdapSettingsSearching = () => {
isRequired
type="text"
id="kc-user-object-classes"
name="userObjectClasses"
name="config.userObjectClasses"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("userLdapFilter")}
labelIcon={
@ -191,34 +218,13 @@ export const LdapSettingsSearching = () => {
}
fieldId="kc-user-ldap-filter"
>
<Controller
name="userLdapFilter"
defaultValue=""
control={control}
render={({ onChange, value }) => (
<Select
toggleId="kc-user-ldap-filter"
required
onToggle={() =>
setIsUserLdapFilterModeDropdownOpen(
!isUserLdapFilterModeDropdownOpen
)
}
isOpen={isUserLdapFilterModeDropdownOpen}
onSelect={(_, value) => {
onChange(value as string);
setIsUserLdapFilterModeDropdownOpen(false);
}}
selections={value}
variant={SelectVariant.single}
>
<SelectOption key={0} value="Choose..." isPlaceholder />
<SelectOption key={1} value="to do " />
</Select>
)}
></Controller>
<TextInput
type="text"
id="kc-user-ldap-filter"
name="config.customUserSearchFilter"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("searchScope")}
labelIcon={
@ -231,7 +237,7 @@ export const LdapSettingsSearching = () => {
fieldId="kc-search-scope"
>
<Controller
name="searchScope"
name="config.searchScope"
defaultValue=""
control={control}
render={({ onChange, value }) => (
@ -249,15 +255,17 @@ export const LdapSettingsSearching = () => {
selections={value}
variant={SelectVariant.single}
>
<SelectOption key={0} value="Choose..." isPlaceholder />
<SelectOption key={1} value="simple" />
<SelectOption key={2} value="none" />
<SelectOption key={5} value="Other" />
<SelectOption
key={0}
value={t("common:choose")}
isPlaceholder
/>
<SelectOption key={1} value={t("oneLevel")} />
<SelectOption key={2} value={t("subtree")} />
</Select>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("readTimeout")}
labelIcon={
@ -272,11 +280,10 @@ export const LdapSettingsSearching = () => {
<TextInput
type="text"
id="kc-read-timeout"
name="readTimeout"
name="config.readTimeout"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("pagination")}
labelIcon={
@ -290,13 +297,13 @@ export const LdapSettingsSearching = () => {
hasNoPaddingTop
>
<Controller
name="pagination"
name="config.pagination"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-console-pagination"}
isChecked={value}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
label={t("common:on")}

View file

@ -1,22 +1,45 @@
import { FormGroup, Switch, TextInput } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import React from "react";
import { HelpItem } from "../components/help-enabler/HelpItem";
import React, { useEffect } 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 { FormAccess } from "../components/form-access/FormAccess";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsSynchronization = () => {
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 { register, control } = useForm<ComponentRepresentation>();
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(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
}, []);
return (
<>
{/* Synchronization settings */}
<FormAccess role="manage-realm" isHorizontal>
<FormGroup
hasNoPaddingTop
label={t("importUsers")}
labelIcon={
<HelpItem
@ -26,19 +49,20 @@ export const LdapSettingsSynchronization = () => {
/>
}
fieldId="kc-import-users"
hasNoPaddingTop
>
<Controller
name="importUsers"
name="config.importEnabled"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-import-users"}
isChecked={value}
name="importEnabled"
label={t("common:on")}
labelOff={t("common:off")}
isChecked={value[0] === "true"}
isDisabled={false}
onChange={onChange}
aria-label={t("importUsers") + " " + t("common:on")}
/>
)}
></Controller>
@ -57,11 +81,12 @@ export const LdapSettingsSynchronization = () => {
<TextInput
type="text"
id="kc-batch-size"
name="batchSize"
name="config.batchSizeForSync"
ref={register}
/>
</FormGroup>
<FormGroup
hasNoPaddingTop
label={t("periodicFullSync")}
labelIcon={
<HelpItem
@ -71,23 +96,13 @@ export const LdapSettingsSynchronization = () => {
/>
}
fieldId="kc-periodic-full-sync"
hasNoPaddingTop
>
<Controller
name="periodicFullSync"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-periodic-full-sync"}
isChecked={value}
isDisabled={false}
onChange={onChange}
label={t("common:on")}
labelOff={t("common:off")}
/>
)}
></Controller>
<TextInput
type="text"
id="kc-batch-size"
name="config.fullSyncPeriod"
ref={register}
/>
</FormGroup>
<FormGroup
label={t("periodicChangedUsersSync")}
@ -101,21 +116,12 @@ export const LdapSettingsSynchronization = () => {
fieldId="kc-periodic-changed-users-sync"
hasNoPaddingTop
>
<Controller
name="periodicChangedUsersSync"
defaultValue={false}
control={control}
render={({ onChange, value }) => (
<Switch
id={"kc-periodic-changed-users-sync"}
isChecked={value}
isDisabled={false}
onChange={onChange}
label={t("common:on")}
labelOff={t("common:off")}
/>
)}
></Controller>
<TextInput
type="text"
id="kc-batch-size"
name="config.changedSyncPeriod"
ref={register}
/>
</FormGroup>
</FormAccess>
</>

View file

@ -20,7 +20,7 @@
"connectionAndAuthenticationSettings": "Connection and authentication settings",
"connectionURL": "Connection URL",
"enableStarttls": "Enable StartTLS",
"enableStartTls": "Enable StartTLS",
"useTruststoreSpi": "Use Truststore SPI",
"connectionPooling": "Connection pooling",
"connectionTimeout": "Connection timeout",
@ -70,6 +70,12 @@
"allowPasswordAuthentication": "Allow password authentication",
"updateFirstLogin": "Update first login",
"always": "Always",
"never": "Never",
"onlyLdaps": "Only for ldaps",
"oneLevel": "One Level",
"subtree": "Subtree",
"learnMore": "Learn more",
"addNewProvider": "Add new provider",
"userFedDeletedSuccess": "The user federation provider has been deleted.",