Merge pull request #400 from mfrances17/add-ldap

User fed: Add LDAP provider and tests
This commit is contained in:
mfrances17 2021-03-02 16:07:32 -05:00 committed by GitHub
commit 511f558834
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 575 additions and 121 deletions

View file

@ -41,7 +41,7 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get("[data-cy=kerberos-card]").click(); cy.get("[data-testid=kerberos-card]").click();
providersPage.fillKerberosRequiredData( providersPage.fillKerberosRequiredData(
firstKerberosName, firstKerberosName,
@ -60,7 +60,7 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -81,7 +81,7 @@ describe("User Fed Kerberos tests", () => {
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.wait(1000); cy.wait(1000);
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -95,7 +95,7 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -113,7 +113,7 @@ describe("User Fed Kerberos tests", () => {
providersPage.cancel(); providersPage.cancel();
cy.wait(1000); cy.wait(1000);
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -133,7 +133,7 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -158,7 +158,7 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
@ -196,8 +196,8 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="my-kerberos-2-dropdown"]').click(); cy.get('[data-testid="my-kerberos-2-dropdown"]').click();
cy.get('[data-cy="card-delete"]').click(); cy.get('[data-testid="card-delete"]').click();
modalUtils.checkModalTitle(deleteModalTitle).confirmModal(); modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
@ -209,13 +209,13 @@ describe("User Fed Kerberos tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToUserFederation(); sidebarPage.goToUserFederation();
cy.get('[data-cy="keycloak-card-title"]') cy.get('[data-testid="keycloak-card-title"]')
.contains(firstKerberosName) .contains(firstKerberosName)
.click(); .click();
cy.wait(1000); cy.wait(1000);
cy.get('[data-testid="action-dropdown"]').click(); cy.get('[data-testid="action-dropdown"]').click();
cy.get('[data-cy="delete-provider-cmd"]').click(); cy.get('[data-testid="delete-kerberos-cmd"]').click();
modalUtils.checkModalTitle(deleteModalTitle).confirmModal(); modalUtils.checkModalTitle(deleteModalTitle).confirmModal();

View file

@ -0,0 +1,188 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin_console/SidebarPage";
import CreateLdapProviderPage from "../support/pages/admin_console/manage/providers/CreateLdapProviderPage";
import Masthead from "../support/pages/admin_console/Masthead";
import ModalUtils from "../support/util/ModalUtils";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const providersPage = new CreateLdapProviderPage();
const modalUtils = new ModalUtils();
const firstLdapName = "my-ldap";
const firstLdapVendor = "Active Directory";
const connectionUrl = "ldap://";
const firstBindType = "simple";
const firstBindDn = "user-1";
const firstBindCreds = "password1";
const firstUsersDn = "user-dn-1";
const firstUserLdapAtt = "uid";
const firstRdnLdapAtt = "uid";
const firstUuidLdapAtt = "entryUUID";
const firstUserObjClasses = "inetOrgPerson, organizationalPerson";
const secondLdapName = `${firstLdapName}-2`;
const secondLdapVendor = "Other";
const secondBindType = "none";
const secondBindDn = "user-2";
const secondBindCreds = "password2";
const secondUsersDn = "user-dn-2";
const secondUserLdapAtt = "cn";
const secondRdnLdapAtt = "cn";
const secondUuidLdapAtt = "objectGUID";
const secondUserObjClasses = "person, organizationalPerson, user";
const defaultPolicy = "DEFAULT";
const newPolicy = "EVICT_WEEKLY";
const defaultLdapDay = "Sunday";
const defaultLdapHour = "00";
const defaultLdapMinute = "00";
const newLdapDay = "Wednesday";
const newLdapHour = "15";
const newLdapMinute = "55";
const createdSuccessMessage = "User federation provider successfully created";
const savedSuccessMessage = "User federation provider successfully saved";
const deletedSuccessMessage = "The user federation provider has been deleted.";
const deleteModalTitle = "Delete user federation provider?";
const disableModalTitle = "Disable user federation provider?";
describe("User Fed LDAP tests", () => {
beforeEach(() => {
cy.visit("");
cy.wait(1000);
loginPage.logIn();
cy.wait(1000);
sidebarPage.goToUserFederation();
cy.wait(1000);
});
it("Create Ldap provider from empty state", () => {
providersPage.clickNewCard("ldap");
providersPage.fillLdapRequiredGeneralData(firstLdapName, firstLdapVendor);
providersPage.fillLdapRequiredConnectionData(
connectionUrl,
firstBindType,
firstBindDn,
firstBindCreds
);
providersPage.fillLdapRequiredSearchingData(
firstUsersDn,
firstUserLdapAtt,
firstRdnLdapAtt,
firstUuidLdapAtt,
firstUserObjClasses
);
providersPage.save();
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it("Update an existing LDAP provider and save", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(newPolicy);
providersPage.changeTime(defaultLdapDay, newLdapDay);
providersPage.changeTime(defaultLdapHour, newLdapHour);
providersPage.changeTime(defaultLdapMinute, newLdapMinute);
providersPage.save();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
cy.wait(1000);
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(newPolicy).should("exist"));
expect(cy.contains(defaultPolicy).should("not.exist"));
});
it("Change existing LDAP provider and click button to cancel", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(newPolicy);
providersPage.changeTime(newLdapDay, defaultLdapDay);
providersPage.changeTime(newLdapHour, defaultLdapHour);
providersPage.changeTime(newLdapMinute, defaultLdapMinute);
providersPage.cancel();
cy.wait(1000);
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(newPolicy);
expect(cy.contains(newLdapDay).should("exist"));
expect(cy.contains(newLdapHour).should("exist"));
expect(cy.contains(newLdapMinute).should("exist"));
expect(cy.contains(defaultLdapMinute).should("not.exist"));
sidebarPage.goToUserFederation();
});
it("Disable an existing LDAP provider", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.disableEnabledSwitch();
modalUtils.checkModalTitle(disableModalTitle).confirmModal();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
cy.wait(1000);
expect(cy.contains("Disabled").should("exist"));
});
it("Enable an existing previously-disabled LDAP provider", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.enableEnabledSwitch();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
cy.wait(1000);
expect(cy.contains("Enabled").should("exist"));
});
it("Create new LDAP provider using the New Provider dropdown", () => {
providersPage.clickMenuCommand("Add new provider", "LDAP");
providersPage.fillLdapRequiredGeneralData(secondLdapName, secondLdapVendor);
providersPage.fillLdapRequiredConnectionData(
connectionUrl,
secondBindType,
secondBindDn,
secondBindCreds
);
providersPage.fillLdapRequiredSearchingData(
secondUsersDn,
secondUserLdapAtt,
secondRdnLdapAtt,
secondUuidLdapAtt,
secondUserObjClasses
);
providersPage.save();
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it("Delete an LDAP provider from card view using the card's menu", () => {
providersPage.deleteCardFromCard(secondLdapName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
it("Delete an LDAP provider using the Settings view's Action menu", () => {
providersPage.deleteCardFromMenu(firstLdapName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
});

View file

@ -19,10 +19,10 @@ export default class CreateKerberosProviderPage {
cancelBtn: string; cancelBtn: string;
constructor() { constructor() {
this.kerberosNameInput = "data-cy=kerberos-name"; this.kerberosNameInput = "data-testid=kerberos-name";
this.kerberosRealmInput = "data-cy=kerberos-realm"; this.kerberosRealmInput = "data-testid=kerberos-realm";
this.kerberosPrincipalInput = "data-cy=kerberos-principal"; this.kerberosPrincipalInput = "data-testid=kerberos-principal";
this.kerberosKeytabInput = "data-cy=kerberos-keytab"; this.kerberosKeytabInput = "data-testid=kerberos-keytab";
this.kerberosEnabledInput = "#Kerberos-switch"; this.kerberosEnabledInput = "#Kerberos-switch";
@ -35,8 +35,8 @@ export default class CreateKerberosProviderPage {
this.kerberosCachePolicyInput = "#kc-cache-policy"; this.kerberosCachePolicyInput = "#kc-cache-policy";
this.kerberosCachePolicyList = "#kc-cache-policy + ul"; this.kerberosCachePolicyList = "#kc-cache-policy + ul";
this.saveBtn = "data-cy=kerberos-save"; this.saveBtn = "data-testid=kerberos-save";
this.cancelBtn = "data-cy=kerberos-cancel"; this.cancelBtn = "data-testid=kerberos-cancel";
} }
//#region Required Settings //#region Required Settings

View file

@ -0,0 +1,191 @@
export default class CreateLdapProviderPage {
ldapNameInput: string;
ldapVendorInput: string;
ldapVendorList: string;
ldapConnectionUrlInput: string;
ldapBindTypeInput: string;
ldapBindTypeList: string;
ldapBindDnInput: string;
ldapBindCredsInput: string;
ldapUsersDnInput: string;
ldapUserLdapAttInput: string;
ldapRdnLdapAttInput: string;
ldapUuidLdapAttInput: string;
ldapUserObjClassesInput: string;
ldapEnabledInput: string;
ldapCacheDayInput: string;
ldapCacheDayList: string;
ldapCacheHourInput: string;
ldapCacheHourList: string;
ldapCacheMinuteInput: string;
ldapCacheMinuteList: string;
ldapCachePolicyInput: string;
ldapCachePolicyList: string;
saveBtn: string;
cancelBtn: string;
constructor() {
// LdapSettingsGeneral required input values
this.ldapNameInput = "data-testid=ldap-name";
this.ldapVendorInput = "#kc-vendor";
this.ldapVendorList = "#kc-vendor + ul";
// LdapSettingsConnection required input values
this.ldapConnectionUrlInput = "data-testid=ldap-connection-url";
this.ldapBindTypeInput = "#kc-bind-type";
this.ldapBindTypeList = "#kc-bind-type + ul";
this.ldapBindDnInput = "data-testid=ldap-bind-dn";
this.ldapBindCredsInput = "data-testid=ldap-bind-credentials";
// LdapSettingsSearching required input values
this.ldapUsersDnInput = "data-testid=ldap-users-dn";
this.ldapUserLdapAttInput = "data-testid=ldap-username-attribute";
this.ldapRdnLdapAttInput = "data-testid=ldap-rdn-attribute";
this.ldapUuidLdapAttInput = "data-testid=ldap-uuid-attribute";
this.ldapUserObjClassesInput = "data-testid=ldap-user-object-classes";
// SettingsCache input values
this.ldapCacheDayInput = "#kc-eviction-day";
this.ldapCacheDayList = "#kc-eviction-day + ul";
this.ldapCacheHourInput = "#kc-eviction-hour";
this.ldapCacheHourList = "#kc-eviction-hour + ul";
this.ldapCacheMinuteInput = "#kc-eviction-minute";
this.ldapCacheMinuteList = "#kc-eviction-minute + ul";
this.ldapCachePolicyInput = "#kc-cache-policy";
this.ldapCachePolicyList = "#kc-cache-policy + ul";
// LDAP settings enabled switch
this.ldapEnabledInput = "#LDAP-switch";
// LDAP action buttons
this.saveBtn = "data-testid=ldap-save";
this.cancelBtn = "data-testid=ldap-cancel";
}
changeTime(oldTime: string, newTime: string) {
cy.contains(oldTime).click();
cy.contains(newTime).click();
return this;
}
deleteCardFromCard(card: string) {
cy.get(`[data-testid=${card}-dropdown]`).click();
cy.get('[data-testid="card-delete"]').click();
return this;
}
deleteCardFromMenu(card: string) {
this.clickExistingCard(card);
cy.get('[data-testid="action-dropdown"]').click();
cy.get('[data-testid="delete-ldap-cmd"]').click();
return this;
}
// Required fields - these always must be filled out when testing a save
fillLdapRequiredGeneralData(name: string, vendor: string) {
if (name) {
cy.get(`[${this.ldapNameInput}]`).type(name);
}
if (vendor) {
cy.get(this.ldapVendorInput).click();
cy.get(this.ldapVendorList).contains(vendor).click();
}
return this;
}
fillLdapRequiredConnectionData(
connectionUrl: string,
bindType: string,
bindDn: string,
bindCreds: string
) {
if (connectionUrl) {
cy.get(`[${this.ldapConnectionUrlInput}]`).type(connectionUrl);
}
if (bindType) {
cy.get(this.ldapBindTypeInput).click();
cy.get(this.ldapBindTypeList).contains(bindType).click();
}
if (bindDn) {
cy.get(`[${this.ldapBindDnInput}]`).type(bindDn);
}
if (bindCreds) {
cy.get(`[${this.ldapBindCredsInput}]`).type(bindCreds);
}
return this;
}
fillLdapRequiredSearchingData(
usersDn: string,
userLdapAtt: string,
rdnLdapAtt: string,
uuidLdapAtt: string,
userObjClasses: string
) {
if (usersDn) {
cy.get(`[${this.ldapUsersDnInput}]`).type(usersDn);
}
if (userLdapAtt) {
cy.get(`[${this.ldapUserLdapAttInput}]`).type(userLdapAtt);
}
if (rdnLdapAtt) {
cy.get(`[${this.ldapRdnLdapAttInput}]`).type(rdnLdapAtt);
}
if (uuidLdapAtt) {
cy.get(`[${this.ldapUuidLdapAttInput}]`).type(uuidLdapAtt);
}
if (userObjClasses) {
cy.get(`[${this.ldapUserObjClassesInput}]`).type(userObjClasses);
}
return this;
}
selectCacheType(cacheType: string) {
cy.get(this.ldapCachePolicyInput).click();
cy.get(this.ldapCachePolicyList).contains(cacheType).click();
return this;
}
clickExistingCard(cardName: string) {
cy.get('[data-testid="keycloak-card-title"]').contains(cardName).click();
cy.wait(1000);
return this;
}
clickMenuCommand(menu: string, command: string) {
cy.contains("button", menu).click();
cy.contains("li", command).click();
return this;
}
clickNewCard(providerType: string) {
cy.get(`[data-testid=${providerType}-card]`).click();
cy.wait(1000);
return this;
}
disableEnabledSwitch() {
cy.get(this.ldapEnabledInput).uncheck({ force: true });
return this;
}
enableEnabledSwitch() {
cy.get(this.ldapEnabledInput).check({ force: true });
return this;
}
save() {
cy.get(`[${this.saveBtn}]`).click();
return this;
}
cancel() {
cy.get(`[${this.cancelBtn}]`).click();
return this;
}
}

View file

@ -58,7 +58,7 @@ export const KeycloakCard = ({
<CardActions> <CardActions>
{dropdownItems && ( {dropdownItems && (
<Dropdown <Dropdown
data-cy={`${title}-dropdown`} data-testid={`${title}-dropdown`}
isPlain isPlain
position={"right"} position={"right"}
toggle={<KebabToggle onToggle={onDropdownToggle} />} toggle={<KebabToggle onToggle={onDropdownToggle} />}
@ -68,7 +68,7 @@ export const KeycloakCard = ({
/> />
)} )}
</CardActions> </CardActions>
<CardTitle data-cy="keycloak-card-title">{title}</CardTitle> <CardTitle data-testid="keycloak-card-title">{title}</CardTitle>
</CardHeader> </CardHeader>
<CardBody /> <CardBody />
<CardFooter> <CardFooter>

View file

@ -60,7 +60,7 @@ const KerberosSettingsHeader = ({
<DropdownItem <DropdownItem
key="delete" key="delete"
onClick={() => toggleDeleteDialog()} onClick={() => toggleDeleteDialog()}
data-cy="delete-provider-cmd" data-testid="delete-kerberos-cmd"
> >
{t("deleteProvider")} {t("deleteProvider")}
</DropdownItem>, </DropdownItem>,
@ -93,10 +93,12 @@ export const UserFederationKerberosSettings = () => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (id !== "new") {
const fetchedComponent = await adminClient.components.findOne({ id }); const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) { if (fetchedComponent) {
setupForm(fetchedComponent); setupForm(fetchedComponent);
} }
}
})(); })();
}, []); }, []);
@ -174,13 +176,13 @@ export const UserFederationKerberosSettings = () => {
<SettingsCache form={form} showSectionHeading /> <SettingsCache form={form} showSectionHeading />
<Form onSubmit={form.handleSubmit(save)}> <Form onSubmit={form.handleSubmit(save)}>
<ActionGroup> <ActionGroup>
<Button variant="primary" type="submit" data-cy="kerberos-save"> <Button variant="primary" type="submit" data-testid="kerberos-save">
{t("common:save")} {t("common:save")}
</Button> </Button>
<Button <Button
variant="link" variant="link"
onClick={() => history.push(`/${realm}/user-federation`)} onClick={() => history.push(`/${realm}/user-federation`)}
data-cy="kerberos-cancel" data-testid="kerberos-cancel"
> >
{t("common:cancel")} {t("common:cancel")}
</Button> </Button>

View file

@ -47,6 +47,7 @@ const LdapSettingsHeader = ({
toggleRemoveUsersDialog, toggleRemoveUsersDialog,
}: LdapSettingsHeaderProps) => { }: LdapSettingsHeaderProps) => {
const { t } = useTranslation("user-federation"); const { t } = useTranslation("user-federation");
const { id } = useParams<{ id: string }>();
const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({ const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({
titleKey: "user-federation:userFedDisableConfirmTitle", titleKey: "user-federation:userFedDisableConfirmTitle",
messageKey: "user-federation:userFedDisableConfirm", messageKey: "user-federation:userFedDisableConfirm",
@ -59,6 +60,9 @@ const LdapSettingsHeader = ({
return ( return (
<> <>
<DisableConfirm /> <DisableConfirm />
{id === "new" ? (
<ViewHeader titleKey="LDAP" subKey="" />
) : (
<ViewHeader <ViewHeader
titleKey="LDAP" titleKey="LDAP"
subKey="" subKey=""
@ -81,11 +85,18 @@ const LdapSettingsHeader = ({
> >
{t("unlinkUsers")} {t("unlinkUsers")}
</DropdownItem>, </DropdownItem>,
<DropdownItem key="remove" onClick={() => toggleRemoveUsersDialog()}> <DropdownItem
key="remove"
onClick={() => toggleRemoveUsersDialog()}
>
{t("removeImported")} {t("removeImported")}
</DropdownItem>, </DropdownItem>,
<DropdownSeparator key="separator" />, <DropdownSeparator key="separator" />,
<DropdownItem key="delete" onClick={() => toggleDeleteDialog()}> <DropdownItem
key="delete"
onClick={() => toggleDeleteDialog()}
data-testid="delete-ldap-cmd"
>
{t("deleteProvider")} {t("deleteProvider")}
</DropdownItem>, </DropdownItem>,
]} ]}
@ -99,6 +110,7 @@ const LdapSettingsHeader = ({
} }
}} }}
/> />
)}
</> </>
); );
}; };
@ -115,10 +127,12 @@ export const UserFederationLdapSettings = () => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (id !== "new") {
const fetchedComponent = await adminClient.components.findOne({ id }); const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) { if (fetchedComponent) {
setupForm(fetchedComponent); setupForm(fetchedComponent);
} }
}
})(); })();
}, []); }, []);
@ -134,11 +148,23 @@ export const UserFederationLdapSettings = () => {
const save = async (component: ComponentRepresentation) => { const save = async (component: ComponentRepresentation) => {
try { try {
if (id) {
if (id === "new") {
await adminClient.components.create(component);
} else {
await adminClient.components.update({ id }, component); await adminClient.components.update({ id }, component);
}
}
setupForm(component as ComponentRepresentation); setupForm(component as ComponentRepresentation);
addAlert(t("saveSuccess"), AlertVariant.success); addAlert(
t(id === "new" ? "createSuccess" : "saveSuccess"),
AlertVariant.success
);
} catch (error) { } catch (error) {
addAlert(`${t("saveError")} '${error}'`, AlertVariant.danger); addAlert(
`${t(id === "new" ? "createError" : "saveError")} '${error}'`,
AlertVariant.danger
);
} }
}; };
@ -179,7 +205,7 @@ export const UserFederationLdapSettings = () => {
<RemoveUsersConfirm /> <RemoveUsersConfirm />
<Controller <Controller
name="config.enabled[0]" name="config.enabled[0]"
defaultValue={["true"]} defaultValue={["true"][0]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<LdapSettingsHeader <LdapSettingsHeader
@ -213,12 +239,13 @@ export const UserFederationLdapSettings = () => {
</ScrollForm> </ScrollForm>
<Form onSubmit={form.handleSubmit(save)}> <Form onSubmit={form.handleSubmit(save)}>
<ActionGroup> <ActionGroup>
<Button variant="primary" type="submit"> <Button variant="primary" type="submit" data-testid="ldap-save">
{t("common:save")} {t("common:save")}
</Button> </Button>
<Button <Button
variant="link" variant="link"
onClick={() => history.push(`/${realm}/user-federation`)} onClick={() => history.push(`/${realm}/user-federation`)}
data-testid="ldap-cancel"
> >
{t("common:cancel")} {t("common:cancel")}
</Button> </Button>

View file

@ -113,7 +113,7 @@ export const UserFederationSection = () => {
onClick={() => { onClick={() => {
toggleDeleteForCard(userFederation.id!); toggleDeleteForCard(userFederation.id!);
}} }}
data-cy="card-delete" data-testid="card-delete"
> >
{t("common:delete")} {t("common:delete")}
</DropdownItem>, </DropdownItem>,
@ -179,7 +179,7 @@ export const UserFederationSection = () => {
<Card <Card
isHoverable isHoverable
onClick={() => history.push(`${url}/kerberos/new`)} onClick={() => history.push(`${url}/kerberos/new`)}
data-cy="kerberos-card" data-testid="kerberos-card"
> >
<CardTitle> <CardTitle>
<Split hasGutter> <Split hasGutter>
@ -190,7 +190,11 @@ export const UserFederationSection = () => {
</Split> </Split>
</CardTitle> </CardTitle>
</Card> </Card>
<Card isHoverable> <Card
isHoverable
onClick={() => history.push(`${url}/ldap/new`)}
data-testid="ldap-card"
>
<CardTitle> <CardTitle>
<Split hasGutter> <Split hasGutter>
<SplitItem> <SplitItem>

View file

@ -107,7 +107,7 @@ export const KerberosSettingsRequired = ({
message: `${t("validateName")}`, message: `${t("validateName")}`,
}, },
})} })}
data-cy="kerberos-name" data-testid="kerberos-name"
/> />
{form.errors.name && ( {form.errors.name && (
<div className="error">{form.errors.name.message}</div> <div className="error">{form.errors.name.message}</div>
@ -137,7 +137,7 @@ export const KerberosSettingsRequired = ({
message: `${t("validateRealm")}`, message: `${t("validateRealm")}`,
}, },
})} })}
data-cy="kerberos-realm" data-testid="kerberos-realm"
/> />
{form.errors.config && {form.errors.config &&
form.errors.config.kerberosRealm && form.errors.config.kerberosRealm &&
@ -171,7 +171,7 @@ export const KerberosSettingsRequired = ({
message: `${t("validateServerPrincipal")}`, message: `${t("validateServerPrincipal")}`,
}, },
})} })}
data-cy="kerberos-principal" data-testid="kerberos-principal"
/> />
{form.errors.config && {form.errors.config &&
form.errors.config.serverPrincipal && form.errors.config.serverPrincipal &&
@ -205,7 +205,7 @@ export const KerberosSettingsRequired = ({
message: `${t("validateKeyTab")}`, message: `${t("validateKeyTab")}`,
}, },
})} })}
data-cy="kerberos-keytab" data-testid="kerberos-keytab"
/> />
{form.errors.config && {form.errors.config &&
form.errors.config.keyTab && form.errors.config.keyTab &&

View file

@ -74,7 +74,7 @@ export const LdapSettingsAdvanced = ({
> >
<Controller <Controller
name="config.validatePasswordPolicy" name="config.validatePasswordPolicy"
defaultValue={"false"} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
@ -103,7 +103,7 @@ export const LdapSettingsAdvanced = ({
> >
<Controller <Controller
name="config.trustEmail" name="config.trustEmail"
defaultValue={"false"} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch

View file

@ -66,6 +66,7 @@ export const LdapSettingsConnection = ({
isRequired isRequired
type="text" type="text"
id="kc-console-connection-url" id="kc-console-connection-url"
data-testid="ldap-connection-url"
name="config.connectionUrl[0]" name="config.connectionUrl[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -167,7 +168,7 @@ export const LdapSettingsConnection = ({
> >
<Controller <Controller
name="config.connectionPooling" name="config.connectionPooling"
defaultValue={false} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
@ -193,7 +194,8 @@ export const LdapSettingsConnection = ({
fieldId="kc-console-connection-timeout" fieldId="kc-console-connection-timeout"
> >
<TextInput <TextInput
type="text" type="number"
min={0}
id="kc-console-connection-timeout" id="kc-console-connection-timeout"
name="config.connectionTimeout[0]" name="config.connectionTimeout[0]"
ref={form.register} ref={form.register}
@ -229,6 +231,7 @@ export const LdapSettingsConnection = ({
}} }}
selections={value} selections={value}
variant={SelectVariant.single} variant={SelectVariant.single}
data-testid="ldap-bind-type"
> >
<SelectOption key={3} value="simple" /> <SelectOption key={3} value="simple" />
<SelectOption key={4} value="none" /> <SelectOption key={4} value="none" />
@ -246,13 +249,27 @@ export const LdapSettingsConnection = ({
/> />
} }
fieldId="kc-console-bind-dn" fieldId="kc-console-bind-dn"
isRequired
> >
<TextInput <TextInput
type="text" type="text"
id="kc-console-bind-dn" id="kc-console-bind-dn"
data-testid="ldap-bind-dn"
name="config.bindDn[0]" name="config.bindDn[0]"
ref={form.register} ref={form.register({
required: {
value: true,
message: `${t("validateBindDn")}`,
},
})}
/> />
{form.errors.config &&
form.errors.config.bindDn &&
form.errors.config.bindDn[0] && (
<div className="error">
{form.errors.config.bindDn[0].message}
</div>
)}
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("bindCredentials")} label={t("bindCredentials")}
@ -271,6 +288,7 @@ export const LdapSettingsConnection = ({
isRequired isRequired
type={isPasswordVisible ? "text" : "password"} type={isPasswordVisible ? "text" : "password"}
id="kc-console-bind-credentials" id="kc-console-bind-credentials"
data-testid="ldap-bind-credentials"
name="config.bindCredential[0]" name="config.bindCredential[0]"
ref={form.register({ ref={form.register({
required: { required: {

View file

@ -10,6 +10,8 @@ import React, { useState } from "react";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import { UseFormMethods, Controller } from "react-hook-form"; import { UseFormMethods, Controller } from "react-hook-form";
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext";
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader"; import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
export type LdapSettingsGeneralProps = { export type LdapSettingsGeneralProps = {
@ -25,6 +27,7 @@ export const LdapSettingsGeneral = ({
}: LdapSettingsGeneralProps) => { }: LdapSettingsGeneralProps) => {
const { t } = useTranslation("user-federation"); const { t } = useTranslation("user-federation");
const helpText = useTranslation("user-federation-help").t; const helpText = useTranslation("user-federation-help").t;
const { realm } = useRealm();
const [isVendorDropdownOpen, setIsVendorDropdownOpen] = useState(false); const [isVendorDropdownOpen, setIsVendorDropdownOpen] = useState(false);
@ -54,8 +57,25 @@ export const LdapSettingsGeneral = ({
<TextInput <TextInput
hidden hidden
type="text" type="text"
id="kc-console-id" id="kc-console-provider-id"
name="id" name="providerId"
defaultValue="ldap"
ref={form.register}
/>
<TextInput
hidden
type="text"
id="kc-console-provider-type"
name="providerType"
defaultValue="org.keycloak.storage.UserStorageProvider"
ref={form.register}
/>
<TextInput
hidden
type="text"
id="kc-console-parentId"
name="parentId"
defaultValue={realm}
ref={form.register} ref={form.register}
/> />
<TextInput <TextInput
@ -69,27 +89,7 @@ export const LdapSettingsGeneral = ({
message: `${t("validateName")}`, message: `${t("validateName")}`,
}, },
})} })}
/> data-testid="ldap-name"
<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 && ( {form.errors.name && (
<div className="error">{form.errors.name.message}</div> <div className="error">{form.errors.name.message}</div>
@ -123,6 +123,7 @@ export const LdapSettingsGeneral = ({
}} }}
selections={value} selections={value}
variant={SelectVariant.single} variant={SelectVariant.single}
// data-testid="ldap-vendor"
> >
<SelectOption key={0} value="ad" isPlaceholder> <SelectOption key={0} value="ad" isPlaceholder>
Active Directory Active Directory

View file

@ -45,7 +45,7 @@ export const LdapSettingsKerberosIntegration = ({
> >
<Controller <Controller
name="config.allowKerberosAuthentication" name="config.allowKerberosAuthentication"
defaultValue={false} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
@ -73,7 +73,7 @@ export const LdapSettingsKerberosIntegration = ({
> >
<Controller <Controller
name="config.useKerberosForPasswordAuthentication" name="config.useKerberosForPasswordAuthentication"
defaultValue={false} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch

View file

@ -97,6 +97,7 @@ export const LdapSettingsSearching = ({
isRequired isRequired
type="text" type="text"
id="kc-console-users-dn" id="kc-console-users-dn"
data-testid="ldap-users-dn"
name="config.usersDn[0]" name="config.usersDn[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -129,6 +130,7 @@ export const LdapSettingsSearching = ({
isRequired isRequired
type="text" type="text"
id="kc-username-ldap-attribute" id="kc-username-ldap-attribute"
data-testid="ldap-username-attribute"
name="config.usernameLDAPAttribute[0]" name="config.usernameLDAPAttribute[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -161,6 +163,7 @@ export const LdapSettingsSearching = ({
isRequired isRequired
type="text" type="text"
id="kc-rdn-ldap-attribute" id="kc-rdn-ldap-attribute"
data-testid="ldap-rdn-attribute"
name="config.rdnLDAPAttribute[0]" name="config.rdnLDAPAttribute[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -193,6 +196,7 @@ export const LdapSettingsSearching = ({
isRequired isRequired
type="text" type="text"
id="kc-uuid-ldap-attribute" id="kc-uuid-ldap-attribute"
data-testid="ldap-uuid-attribute"
name="config.uuidLDAPAttribute[0]" name="config.uuidLDAPAttribute[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -225,6 +229,7 @@ export const LdapSettingsSearching = ({
isRequired isRequired
type="text" type="text"
id="kc-user-object-classes" id="kc-user-object-classes"
data-testid="ldap-user-object-classes"
name="config.userObjectClasses[0]" name="config.userObjectClasses[0]"
ref={form.register({ ref={form.register({
required: { required: {
@ -256,8 +261,20 @@ export const LdapSettingsSearching = ({
type="text" type="text"
id="kc-user-ldap-filter" id="kc-user-ldap-filter"
name="config.customUserSearchFilter[0]" name="config.customUserSearchFilter[0]"
ref={form.register} ref={form.register({
pattern: {
value: /(\(.*\))$/,
message: `${t("validateCustomUserSearchFilter")}`,
},
})}
/> />
{form.errors.config &&
form.errors.config.customUserSearchFilter &&
form.errors.config.customUserSearchFilter[0] && (
<div className="error">
{form.errors.config.customUserSearchFilter[0].message}
</div>
)}
</FormGroup> </FormGroup>
<FormGroup <FormGroup
@ -312,7 +329,8 @@ export const LdapSettingsSearching = ({
fieldId="kc-read-timeout" fieldId="kc-read-timeout"
> >
<TextInput <TextInput
type="text" type="number"
min={0}
id="kc-read-timeout" id="kc-read-timeout"
name="config.readTimeout[0]" name="config.readTimeout[0]"
ref={form.register} ref={form.register}
@ -332,7 +350,7 @@ export const LdapSettingsSearching = ({
> >
<Controller <Controller
name="config.pagination" name="config.pagination"
defaultValue={false} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch

View file

@ -44,7 +44,7 @@ export const LdapSettingsSynchronization = ({
> >
<Controller <Controller
name="config.importEnabled" name="config.importEnabled"
defaultValue={false} defaultValue={["false"]}
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
@ -71,7 +71,8 @@ export const LdapSettingsSynchronization = ({
fieldId="kc-batch-size" fieldId="kc-batch-size"
> >
<TextInput <TextInput
type="text" type="number"
min={0}
id="kc-batch-size" id="kc-batch-size"
name="config.batchSizeForSync[0]" name="config.batchSizeForSync[0]"
ref={form.register} ref={form.register}
@ -92,7 +93,8 @@ export const LdapSettingsSynchronization = ({
fieldId="kc-full-sync-period" fieldId="kc-full-sync-period"
> >
<TextInput <TextInput
type="text" type="number"
min={-1}
id="kc-full-sync-period" id="kc-full-sync-period"
name="config.fullSyncPeriod[0]" name="config.fullSyncPeriod[0]"
ref={form.register} ref={form.register}
@ -113,7 +115,8 @@ export const LdapSettingsSynchronization = ({
hasNoPaddingTop hasNoPaddingTop
> >
<TextInput <TextInput
type="text" type="number"
min={-1}
id="kc-changed-users-sync-period" id="kc-changed-users-sync-period"
name="config.changedSyncPeriod[0]" name="config.changedSyncPeriod[0]"
ref={form.register} ref={form.register}

View file

@ -104,12 +104,14 @@
"validateServerPrincipal":"You must enter a server principal", "validateServerPrincipal":"You must enter a server principal",
"validateKeyTab": "You must enter a key tab", "validateKeyTab": "You must enter a key tab",
"validateConnectionUrl": "You must enter a connection URL", "validateConnectionUrl": "You must enter a connection URL",
"validateBindCredentials": "You must enter bind credentials", "validateBindDn": "You must enter the DN of the LDAP admin",
"validateBindCredentials": "You must enter the password of the LDAP admin",
"validateUuidLDAPAttribute": "You must enter a UUID LDAP attribute", "validateUuidLDAPAttribute": "You must enter a UUID LDAP attribute",
"validateUserObjectClasses": "You must enter one or more user object classes", "validateUserObjectClasses": "You must enter one or more user object classes",
"validateUsersDn": "You must enter users DN", "validateUsersDn": "You must enter users DN",
"validateUsernameLDAPAttribute": "You must enter a username LDAP attribute", "validateUsernameLDAPAttribute": "You must enter a username LDAP attribute",
"validateRdnLdapAttribute": "You must enter an RDN LDAP attribute", "validateRdnLdapAttribute": "You must enter an RDN LDAP attribute",
"validateCustomUserSearchFilter": "Filter must be enclosed in parentheses, for example: (filter)",
"id": "ID", "id": "ID",
"mapperType": "Mapper type", "mapperType": "Mapper type",

View file

@ -126,7 +126,7 @@ export const SettingsCache = ({
}} }}
selections={value} selections={value}
variant={SelectVariant.single} variant={SelectVariant.single}
data-cy="kerberos-cache-policy" data-testid="kerberos-cache-policy"
> >
<SelectOption key={0} value={["DEFAULT"]} isPlaceholder /> <SelectOption key={0} value={["DEFAULT"]} isPlaceholder />
<SelectOption key={1} value={["EVICT_DAILY"]} /> <SelectOption key={1} value={["EVICT_DAILY"]} />
@ -156,7 +156,7 @@ export const SettingsCache = ({
control={form.control} control={form.control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Select <Select
data-cy="cache-day" data-testid="cache-day"
toggleId="kc-eviction-day" toggleId="kc-eviction-day"
required required
onToggle={() => onToggle={() =>
@ -294,7 +294,7 @@ export const SettingsCache = ({
id="kc-max-lifespan" id="kc-max-lifespan"
name="config.maxLifespan[0]" name="config.maxLifespan[0]"
ref={form.register} ref={form.register}
data-cy="kerberos-cache-lifespan" data-testid="kerberos-cache-lifespan"
/> />
</FormGroup> </FormGroup>
) : ( ) : (