Merge pull request #490 from mfrances17/ldap-mappers-layout
User fed mappers layout and partial logic
This commit is contained in:
commit
f3dde7d2ee
35 changed files with 1802 additions and 179 deletions
|
@ -157,8 +157,8 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
)}
|
)}
|
||||||
{isBuiltIn && rows.length === 0 && (
|
{isBuiltIn && rows.length === 0 && (
|
||||||
<ListEmptyState
|
<ListEmptyState
|
||||||
message={t("emptyMappers")}
|
message={t("common:emptyMappers")}
|
||||||
instructions={t("emptyBuiltInMappersInstructions")}
|
instructions={t("common:emptyBuiltInMappersInstructions")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -146,7 +146,7 @@ export const RoleMappingForm = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewHeader
|
<ViewHeader
|
||||||
titleKey="client-scopes:addMapper"
|
titleKey="common:addMapper"
|
||||||
subKey="client-scopes:addMapperExplain"
|
subKey="client-scopes:addMapperExplain"
|
||||||
/>
|
/>
|
||||||
<PageSection variant="light">
|
<PageSection variant="light">
|
||||||
|
@ -156,11 +156,11 @@ export const RoleMappingForm = () => {
|
||||||
role="manage-clients"
|
role="manage-clients"
|
||||||
>
|
>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("protocolMapper")}
|
label={t("common:mapperType")}
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="client-scopes-help:protocolMapper"
|
helpText="client-scopes-help:protocolMapper"
|
||||||
forLabel={t("protocolMapper")}
|
forLabel={t("common:mapperType")}
|
||||||
forID="protocolMapper"
|
forID="protocolMapper"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,12 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
mappers as ProtocolMapperRepresentation[]
|
mappers as ProtocolMapperRepresentation[]
|
||||||
);
|
);
|
||||||
refresh();
|
refresh();
|
||||||
addAlert(t("mappingCreatedSuccess"), AlertVariant.success);
|
addAlert(t("common:mappingCreatedSuccess"), AlertVariant.success);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
addAlert(t("mappingCreatedError", { error }), AlertVariant.danger);
|
addAlert(
|
||||||
|
t("common:mappingCreatedError", { error }),
|
||||||
|
AlertVariant.danger
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -119,7 +122,7 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
key={key}
|
key={key}
|
||||||
loader={loader}
|
loader={loader}
|
||||||
ariaLabelKey="client-scopes:clientScopeList"
|
ariaLabelKey="client-scopes:clientScopeList"
|
||||||
searchPlaceholderKey="client-scopes:mappersSearchFor"
|
searchPlaceholderKey="common:searchForMapper"
|
||||||
toolbarItem={
|
toolbarItem={
|
||||||
<Dropdown
|
<Dropdown
|
||||||
onSelect={() => setMapperAction(false)}
|
onSelect={() => setMapperAction(false)}
|
||||||
|
@ -130,7 +133,7 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
onToggle={() => setMapperAction(!mapperAction)}
|
onToggle={() => setMapperAction(!mapperAction)}
|
||||||
toggleIndicator={CaretDownIcon}
|
toggleIndicator={CaretDownIcon}
|
||||||
>
|
>
|
||||||
{t("addMapper")}
|
{t("common:addMapper")}
|
||||||
</DropdownToggle>
|
</DropdownToggle>
|
||||||
}
|
}
|
||||||
isOpen={mapperAction}
|
isOpen={mapperAction}
|
||||||
|
@ -159,11 +162,14 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
id: clientScope.id!,
|
id: clientScope.id!,
|
||||||
mapperId: mapper.id!,
|
mapperId: mapper.id!,
|
||||||
});
|
});
|
||||||
addAlert(t("mappingDeletedSuccess"), AlertVariant.success);
|
addAlert(
|
||||||
|
t("common:mappingDeletedSuccess"),
|
||||||
|
AlertVariant.success
|
||||||
|
);
|
||||||
refresh();
|
refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
addAlert(
|
addAlert(
|
||||||
t("mappingDeletedError", { error }),
|
t("common:mappingDeletedError", { error }),
|
||||||
AlertVariant.danger
|
AlertVariant.danger
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -186,9 +192,9 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
]}
|
]}
|
||||||
emptyState={
|
emptyState={
|
||||||
<ListEmptyState
|
<ListEmptyState
|
||||||
message={t("emptyMappers")}
|
message={t("common:emptyMappers")}
|
||||||
instructions={t("emptyMappersInstructions")}
|
instructions={t("common:emptyMappersInstructions")}
|
||||||
primaryActionText={t("emptyPrimaryAction")}
|
primaryActionText={t("common:emptyPrimaryAction")}
|
||||||
onPrimaryAction={() => toggleAddMapperDialog(true)}
|
onPrimaryAction={() => toggleAddMapperDialog(true)}
|
||||||
secondaryActions={[
|
secondaryActions={[
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useHistory, useParams, useRouteMatch } from "react-router-dom";
|
import { useHistory, useParams } from "react-router-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useErrorHandler } from "react-error-boundary";
|
import { useErrorHandler } from "react-error-boundary";
|
||||||
import {
|
import {
|
||||||
|
@ -109,8 +109,8 @@ export const MappingDetails = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
|
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
|
||||||
titleKey: "client-scopes:deleteMappingTitle",
|
titleKey: "common:deleteMappingTitle",
|
||||||
messageKey: "client-scopes:deleteMappingConfirm",
|
messageKey: "common:deleteMappingConfirm",
|
||||||
continueButtonLabel: "common:delete",
|
continueButtonLabel: "common:delete",
|
||||||
continueButtonVariant: ButtonVariant.danger,
|
continueButtonVariant: ButtonVariant.danger,
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
|
@ -119,10 +119,13 @@ export const MappingDetails = () => {
|
||||||
id,
|
id,
|
||||||
mapperId: mapperId,
|
mapperId: mapperId,
|
||||||
});
|
});
|
||||||
addAlert(t("mappingDeletedSuccess"), AlertVariant.success);
|
addAlert(t("common:mappingDeletedSuccess"), AlertVariant.success);
|
||||||
history.push(`/${realm}/client-scopes/${id}/mappers`);
|
history.push(`/${realm}/client-scopes/${id}/mappers`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
addAlert(t("mappingDeletedError", { error }), AlertVariant.danger);
|
addAlert(
|
||||||
|
t("common:mappingDeletedError", { error }),
|
||||||
|
AlertVariant.danger
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -150,7 +153,7 @@ export const MappingDetails = () => {
|
||||||
<>
|
<>
|
||||||
<DeleteConfirm />
|
<DeleteConfirm />
|
||||||
<ViewHeader
|
<ViewHeader
|
||||||
titleKey={mapping ? mapping.name! : t("addMapper")}
|
titleKey={mapping ? mapping.name! : t("common:addMapper")}
|
||||||
subKey={mapperId.match(isGuid) ? mapperId : ""}
|
subKey={mapperId.match(isGuid) ? mapperId : ""}
|
||||||
badge={mapping?.protocol}
|
badge={mapping?.protocol}
|
||||||
dropdownItems={
|
dropdownItems={
|
||||||
|
|
|
@ -322,7 +322,7 @@ export const ClientScopeForm = () => {
|
||||||
<Tab
|
<Tab
|
||||||
isHidden={!id}
|
isHidden={!id}
|
||||||
eventKey="mappers"
|
eventKey="mappers"
|
||||||
title={<TabTitleText>{t("mappers")}</TabTitleText>}
|
title={<TabTitleText>{t("common:mappers")}</TabTitleText>}
|
||||||
>
|
>
|
||||||
{clientScope && (
|
{clientScope && (
|
||||||
<MapperList clientScope={clientScope} refresh={refresh} />
|
<MapperList clientScope={clientScope} refresh={refresh} />
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
"deletedSuccess": "The client scope has been deleted",
|
"deletedSuccess": "The client scope has been deleted",
|
||||||
"deleteError": "Could not delete client scope: {{error}}",
|
"deleteError": "Could not delete client scope: {{error}}",
|
||||||
"includeInTokenScope": "Include in token scope",
|
"includeInTokenScope": "Include in token scope",
|
||||||
"mappingDetails": "Mapper details",
|
|
||||||
"mappingCreatedSuccess": "Mapping successfully created",
|
|
||||||
"mappingCreatedError": "Could not create mapping: '{{error}}'",
|
|
||||||
"deleteMappingTitle": "Delete mapping?",
|
|
||||||
"deleteMappingConfirm": "Are you sure you want to delete this mapping?",
|
|
||||||
"mappingUpdatedSuccess": "Mapping successfully updated",
|
"mappingUpdatedSuccess": "Mapping successfully updated",
|
||||||
"mappingUpdatedError": "Could not update mapping: '{{error}}'",
|
"mappingUpdatedError": "Could not update mapping: '{{error}}'",
|
||||||
"realmRolePrefix": "Realm role prefix",
|
"realmRolePrefix": "Realm role prefix",
|
||||||
|
@ -28,11 +23,7 @@
|
||||||
"createError": "Could not create client scope: '{{error}}'",
|
"createError": "Could not create client scope: '{{error}}'",
|
||||||
"updateSuccess": "Client scope updated",
|
"updateSuccess": "Client scope updated",
|
||||||
"updateError": "Could not update client scope: '{{error}}'",
|
"updateError": "Could not update client scope: '{{error}}'",
|
||||||
"mappers": "Mappers",
|
|
||||||
"mappersSearchFor": "Search for mapper",
|
|
||||||
"addMapper": "Add mapper",
|
|
||||||
"addMapperExplain": "If you want more fine-grain control, you can create protocol mapper on this client",
|
"addMapperExplain": "If you want more fine-grain control, you can create protocol mapper on this client",
|
||||||
"protocolMapper": "Mapper type",
|
|
||||||
"realmRoles": "Realm roles",
|
"realmRoles": "Realm roles",
|
||||||
"selectARole": "Select a role",
|
"selectARole": "Select a role",
|
||||||
"clientRoles": "Client roles",
|
"clientRoles": "Client roles",
|
||||||
|
@ -44,13 +35,8 @@
|
||||||
"mapperCreateError": "Could not create mapping: {{error}}",
|
"mapperCreateError": "Could not create mapping: {{error}}",
|
||||||
"fromPredefinedMapper": "From predefined mappers",
|
"fromPredefinedMapper": "From predefined mappers",
|
||||||
"byConfiguration": "By configuration",
|
"byConfiguration": "By configuration",
|
||||||
"emptyMappers": "No mappers",
|
|
||||||
"emptyMappersInstructions": "If you want to add mappers, please click the button below to add some predefined mappers or to configure a new mapper.",
|
|
||||||
"emptyBuiltInMappersInstructions": "All built in mappers were added to this client",
|
"emptyBuiltInMappersInstructions": "All built in mappers were added to this client",
|
||||||
"emptyPrimaryAction": "Add predefined mapper",
|
|
||||||
"emptySecondaryAction": "Configure a new mapper",
|
"emptySecondaryAction": "Configure a new mapper",
|
||||||
"mappingDeletedSuccess": "Mapping successfully deleted",
|
|
||||||
"mappingDeletedError": "Could not delete mapping: '{{error}}'",
|
|
||||||
"displayOnConsentScreen": "Display on consent screen",
|
"displayOnConsentScreen": "Display on consent screen",
|
||||||
"consentScreenText": "Consent screen text",
|
"consentScreenText": "Consent screen text",
|
||||||
"guiOrder": "Display Order",
|
"guiOrder": "Display Order",
|
||||||
|
|
|
@ -22,11 +22,11 @@ export const ClientDescription = () => {
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="clients-help:clientID"
|
helpText="clients-help:clientID"
|
||||||
forLabel={t("clientID")}
|
forLabel={t("common:clientID")}
|
||||||
forID="kc-client-id"
|
forID="kc-client-id"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={t("clientID")}
|
label={t("common:clientID")}
|
||||||
fieldId="kc-client-id"
|
fieldId="kc-client-id"
|
||||||
helperTextInvalid={t("common:required")}
|
helperTextInvalid={t("common:required")}
|
||||||
validated={
|
validated={
|
||||||
|
|
|
@ -144,7 +144,7 @@ export const ClientsSection = () => {
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
name: "clientId",
|
name: "clientId",
|
||||||
displayKey: "clients:clientID",
|
displayKey: "common:clientID",
|
||||||
cellRenderer: ClientDetailLink,
|
cellRenderer: ClientDetailLink,
|
||||||
},
|
},
|
||||||
{ name: "protocol", displayKey: "common:type" },
|
{ name: "protocol", displayKey: "common:type" },
|
||||||
|
|
|
@ -74,7 +74,7 @@ export const InitialAccessTokenList = () => {
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
name: "id",
|
name: "id",
|
||||||
displayKey: "clients:id",
|
displayKey: "common:id",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "timestamp",
|
name: "timestamp",
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"implicitFlow": "Implicit flow",
|
"implicitFlow": "Implicit flow",
|
||||||
"createClient": "Create client",
|
"createClient": "Create client",
|
||||||
"importClient": "Import client",
|
"importClient": "Import client",
|
||||||
"clientID": "Client ID",
|
|
||||||
"homeURL": "Home URL",
|
"homeURL": "Home URL",
|
||||||
"webOrigins": "Web origins",
|
"webOrigins": "Web origins",
|
||||||
"addWebOrigins": "Add web origins",
|
"addWebOrigins": "Add web origins",
|
||||||
|
@ -86,7 +85,6 @@
|
||||||
"tokenDeleteConfirmTitle": "Delete initial access token?",
|
"tokenDeleteConfirmTitle": "Delete initial access token?",
|
||||||
"tokenDeleteSuccess": "initial access token created successfully",
|
"tokenDeleteSuccess": "initial access token created successfully",
|
||||||
"tokenDeleteError": "Could not delete initial access token: '{{error}}'",
|
"tokenDeleteError": "Could not delete initial access token: '{{error}}'",
|
||||||
"id": "ID",
|
|
||||||
"timestamp": "Created date",
|
"timestamp": "Created date",
|
||||||
"expires": "Expires",
|
"expires": "Expires",
|
||||||
"count": "Count",
|
"count": "Count",
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
"groups": "Groups",
|
"groups": "Groups",
|
||||||
"sessions": "Sessions",
|
"sessions": "Sessions",
|
||||||
"events": "Events",
|
"events": "Events",
|
||||||
|
"mappers": "Mappers",
|
||||||
|
|
||||||
"configure": "Configure",
|
"configure": "Configure",
|
||||||
"realmSettings": "Realm settings",
|
"realmSettings": "Realm settings",
|
||||||
|
@ -94,6 +95,25 @@
|
||||||
"minutes": "Minutes",
|
"minutes": "Minutes",
|
||||||
"hours": "Hours",
|
"hours": "Hours",
|
||||||
"days": "Days"
|
"days": "Days"
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"attributes": "Attributes",
|
||||||
|
"clientId": "Client ID",
|
||||||
|
"id": "ID",
|
||||||
|
|
||||||
|
"addMapper": "Add mapper",
|
||||||
|
"searchForMapper": "Search for mapper",
|
||||||
|
"mapperType": "Mapper type",
|
||||||
|
"mappingDeletedSuccess": "Mapping successfully deleted",
|
||||||
|
"mappingDeletedError": "Could not delete mapping: '{{error}}'",
|
||||||
|
"mappingDetails": "Mapper details",
|
||||||
|
"mappingCreatedSuccess": "Mapping successfully created",
|
||||||
|
"mappingCreatedError": "Could not create mapping: '{{error}}'",
|
||||||
|
"deleteMappingTitle": "Delete mapping?",
|
||||||
|
"deleteMappingConfirm": "Are you sure you want to delete this mapping?",
|
||||||
|
|
||||||
|
"emptyMappers": "No mappers",
|
||||||
|
"emptyMappersInstructions": "If you want to add mappers, please click the button below to add some predefined mappers or to configure a new mapper.",
|
||||||
|
"emptyPrimaryAction": "Add predefined mapper"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ export type DataListProps<T> = {
|
||||||
* <KeycloakDataTable columns={[
|
* <KeycloakDataTable columns={[
|
||||||
* {
|
* {
|
||||||
* name: "clientId", //name of the field from the array of object the loader returns to display in this column
|
* name: "clientId", //name of the field from the array of object the loader returns to display in this column
|
||||||
* displayKey: "clients:clientID", //i18n key to use to lookup the name of the column header
|
* displayKey: "common:clientID", //i18n key to use to lookup the name of the column header
|
||||||
* cellRenderer: ClientDetailLink, //optionally you can use a component to render the column when you don't want just the content of the field, the whole row / entire object is passed in.
|
* cellRenderer: ClientDetailLink, //optionally you can use a component to render the column when you don't want just the content of the field, the whole row / entire object is passed in.
|
||||||
* }
|
* }
|
||||||
* ]}
|
* ]}
|
||||||
|
|
|
@ -174,7 +174,7 @@ export const GroupsSection = () => {
|
||||||
<Tab
|
<Tab
|
||||||
data-testid="attributes"
|
data-testid="attributes"
|
||||||
eventKey={2}
|
eventKey={2}
|
||||||
title={<TabTitleText>{t("attributes")}</TabTitleText>}
|
title={<TabTitleText>{t("common:attributes")}</TabTitleText>}
|
||||||
>
|
>
|
||||||
<GroupAttributes />
|
<GroupAttributes />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
|
@ -327,7 +327,7 @@ export const RealmRoleTabs = () => {
|
||||||
) : null}
|
) : null}
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="attributes"
|
eventKey="attributes"
|
||||||
title={<TabTitleText>{t("attributes")}</TabTitleText>}
|
title={<TabTitleText>{t("common:attributes")}</TabTitleText>}
|
||||||
>
|
>
|
||||||
<AttributesForm
|
<AttributesForm
|
||||||
form={form}
|
form={form}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"roles": {
|
"roles": {
|
||||||
"attributes": "Attributes",
|
|
||||||
"addAttributeText": "Add an attribute",
|
"addAttributeText": "Add an attribute",
|
||||||
"deleteAttributeText": "Delete an attribute",
|
"deleteAttributeText": "Delete an attribute",
|
||||||
"associatedRolesText": "Associated roles",
|
"associatedRolesText": "Associated roles",
|
||||||
|
@ -59,7 +58,6 @@
|
||||||
"noDirectUsers": "No direct users",
|
"noDirectUsers": "No direct users",
|
||||||
"noUsersEmptyStateDescription": "Only the users with this role directly assigned will appear under this tab. If you need to find users assigned to this role, go to",
|
"noUsersEmptyStateDescription": "Only the users with this role directly assigned will appear under this tab. If you need to find users assigned to this role, go to",
|
||||||
"noUsersEmptyStateDescriptionContinued": "to find them. Users that already have this role as an effective role cannot be added here.",
|
"noUsersEmptyStateDescriptionContinued": "to find them. Users that already have this role as an effective role cannot be added here.",
|
||||||
"id": "ID",
|
|
||||||
"groups": "Groups",
|
"groups": "Groups",
|
||||||
"or": "or",
|
"or": "or",
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { RoleMappingForm } from "./client-scopes/add/RoleMappingForm";
|
||||||
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
|
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
|
||||||
import { SearchGroups } from "./groups/SearchGroups";
|
import { SearchGroups } from "./groups/SearchGroups";
|
||||||
import { CreateInitialAccessToken } from "./clients/initial-access/CreateInitialAccessToken";
|
import { CreateInitialAccessToken } from "./clients/initial-access/CreateInitialAccessToken";
|
||||||
|
import { LdapMappingDetails } from "./user-federation/ldap/mappers/LdapMappingDetails";
|
||||||
|
|
||||||
export type RouteDef = BreadcrumbsRoute & {
|
export type RouteDef = BreadcrumbsRoute & {
|
||||||
access: AccessType;
|
access: AccessType;
|
||||||
|
@ -95,13 +96,13 @@ export const routes: RoutesFn = (t: TFunction) => [
|
||||||
{
|
{
|
||||||
path: "/:realm/client-scopes/:id/mappers/oidc-role-name-mapper",
|
path: "/:realm/client-scopes/:id/mappers/oidc-role-name-mapper",
|
||||||
component: RoleMappingForm,
|
component: RoleMappingForm,
|
||||||
breadcrumb: t("client-scopes:mappingDetails"),
|
breadcrumb: t("common:mappingDetails"),
|
||||||
access: "view-clients",
|
access: "view-clients",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:realm/client-scopes/:id/mappers/:mapperId",
|
path: "/:realm/client-scopes/:id/mappers/:mapperId",
|
||||||
component: MappingDetails,
|
component: MappingDetails,
|
||||||
breadcrumb: t("client-scopes:mappingDetails"),
|
breadcrumb: t("common:mappingDetails"),
|
||||||
access: "view-clients",
|
access: "view-clients",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -200,12 +201,6 @@ export const routes: RoutesFn = (t: TFunction) => [
|
||||||
breadcrumb: null,
|
breadcrumb: null,
|
||||||
access: "view-realm",
|
access: "view-realm",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/:realm/user-federation/ldap",
|
|
||||||
component: UserFederationSection,
|
|
||||||
breadcrumb: null,
|
|
||||||
access: "view-realm",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/:realm/user-federation/kerberos/:id",
|
path: "/:realm/user-federation/kerberos/:id",
|
||||||
component: UserFederationKerberosSettings,
|
component: UserFederationKerberosSettings,
|
||||||
|
@ -219,11 +214,23 @@ export const routes: RoutesFn = (t: TFunction) => [
|
||||||
access: "view-realm",
|
access: "view-realm",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:realm/user-federation/ldap/:id",
|
path: "/:realm/user-federation/ldap",
|
||||||
|
component: UserFederationSection,
|
||||||
|
breadcrumb: null,
|
||||||
|
access: "view-realm",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/:realm/user-federation/ldap/:id/:tab?",
|
||||||
component: UserFederationLdapSettings,
|
component: UserFederationLdapSettings,
|
||||||
breadcrumb: t("common:settings"),
|
breadcrumb: t("common:settings"),
|
||||||
access: "view-realm",
|
access: "view-realm",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/:realm/user-federation/ldap/:id/:tab/:mapperId",
|
||||||
|
component: LdapMappingDetails,
|
||||||
|
breadcrumb: t("common:mappingDetails"),
|
||||||
|
access: "view-realm",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/:realm/user-federation/ldap/new",
|
path: "/:realm/user-federation/ldap/new",
|
||||||
component: UserFederationLdapSettings,
|
component: UserFederationLdapSettings,
|
||||||
|
|
|
@ -26,7 +26,7 @@ SimpleList.args = {
|
||||||
ariaLabelKey: "clients:clientList",
|
ariaLabelKey: "clients:clientList",
|
||||||
searchPlaceholderKey: "common:search",
|
searchPlaceholderKey: "common:search",
|
||||||
columns: [
|
columns: [
|
||||||
{ name: "clientId", displayKey: "clients:clientID" },
|
{ name: "clientId", displayKey: "common:clientID" },
|
||||||
{ name: "protocol", displayKey: "common:type" },
|
{ name: "protocol", displayKey: "common:type" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
|
|
|
@ -8,6 +8,8 @@ import {
|
||||||
DropdownSeparator,
|
DropdownSeparator,
|
||||||
Form,
|
Form,
|
||||||
PageSection,
|
PageSection,
|
||||||
|
Tab,
|
||||||
|
TabTitleText,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
|
|
||||||
import { LdapSettingsAdvanced } from "./ldap/LdapSettingsAdvanced";
|
import { LdapSettingsAdvanced } from "./ldap/LdapSettingsAdvanced";
|
||||||
|
@ -31,6 +33,9 @@ import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||||
import { useHistory, useParams } from "react-router-dom";
|
import { useHistory, useParams } from "react-router-dom";
|
||||||
import { ScrollForm } from "../components/scroll-form/ScrollForm";
|
import { ScrollForm } from "../components/scroll-form/ScrollForm";
|
||||||
|
|
||||||
|
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||||
|
import { LdapMapperList } from "./ldap/mappers/LdapMapperList";
|
||||||
|
|
||||||
type LdapSettingsHeaderProps = {
|
type LdapSettingsHeaderProps = {
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -276,44 +281,59 @@ export const UserFederationLdapSettings = () => {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<PageSection variant="light" isFilled>
|
<PageSection variant="light" isFilled>
|
||||||
<ScrollForm
|
<KeycloakTabs isBox>
|
||||||
sections={[
|
<Tab
|
||||||
t("generalOptions"),
|
id="settings"
|
||||||
t("connectionAndAuthenticationSettings"),
|
eventKey="settings"
|
||||||
t("ldapSearchingAndUpdatingSettings"),
|
title={<TabTitleText>{t("common:settings")}</TabTitleText>}
|
||||||
t("synchronizationSettings"),
|
>
|
||||||
t("kerberosIntegration"),
|
<ScrollForm
|
||||||
t("cacheSettings"),
|
sections={[
|
||||||
t("advancedSettings"),
|
t("generalOptions"),
|
||||||
]}
|
t("connectionAndAuthenticationSettings"),
|
||||||
>
|
t("ldapSearchingAndUpdatingSettings"),
|
||||||
<LdapSettingsGeneral form={form} />
|
t("synchronizationSettings"),
|
||||||
<LdapSettingsConnection form={form} />
|
t("kerberosIntegration"),
|
||||||
<LdapSettingsSearching form={form} />
|
t("cacheSettings"),
|
||||||
<LdapSettingsSynchronization form={form} />
|
t("advancedSettings"),
|
||||||
<LdapSettingsKerberosIntegration form={form} />
|
]}
|
||||||
<SettingsCache form={form} />
|
|
||||||
<LdapSettingsAdvanced form={form} />
|
|
||||||
</ScrollForm>
|
|
||||||
<Form onSubmit={form.handleSubmit(save)}>
|
|
||||||
<ActionGroup className="keycloak__form_actions">
|
|
||||||
<Button
|
|
||||||
isDisabled={!form.formState.isDirty}
|
|
||||||
variant="primary"
|
|
||||||
type="submit"
|
|
||||||
data-testid="ldap-save"
|
|
||||||
>
|
>
|
||||||
{t("common:save")}
|
<LdapSettingsGeneral form={form} />
|
||||||
</Button>
|
<LdapSettingsConnection form={form} />
|
||||||
<Button
|
<LdapSettingsSearching form={form} />
|
||||||
variant="link"
|
<LdapSettingsSynchronization form={form} />
|
||||||
onClick={() => history.push(`/${realm}/user-federation`)}
|
<LdapSettingsKerberosIntegration form={form} />
|
||||||
data-testid="ldap-cancel"
|
<SettingsCache form={form} />
|
||||||
>
|
<LdapSettingsAdvanced form={form} />
|
||||||
{t("common:cancel")}
|
</ScrollForm>
|
||||||
</Button>
|
<Form onSubmit={form.handleSubmit(save)}>
|
||||||
</ActionGroup>
|
<ActionGroup className="keycloak__form_actions">
|
||||||
</Form>
|
<Button
|
||||||
|
isDisabled={!form.formState.isDirty}
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
data-testid="ldap-save"
|
||||||
|
>
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="link"
|
||||||
|
onClick={() => history.push(`/${realm}/user-federation`)}
|
||||||
|
data-testid="ldap-cancel"
|
||||||
|
>
|
||||||
|
{t("common:cancel")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</Form>
|
||||||
|
</Tab>
|
||||||
|
<Tab
|
||||||
|
id="mappers"
|
||||||
|
eventKey="mappers"
|
||||||
|
title={<TabTitleText>{t("common:mappers")}</TabTitleText>}
|
||||||
|
>
|
||||||
|
<LdapMapperList />
|
||||||
|
</Tab>
|
||||||
|
</KeycloakTabs>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -66,9 +66,6 @@
|
||||||
"editModeKerberosHelp": "READ_ONLY means that password updates are not allowed and user always authenticates with Kerberos password. UNSYNCED means that the user can change the password in the Keycloak database and this one will be used instead of the Kerberos password.",
|
"editModeKerberosHelp": "READ_ONLY means that password updates are not allowed and user always authenticates with Kerberos password. UNSYNCED means that the user can change the password in the Keycloak database and this one will be used instead of the Kerberos password.",
|
||||||
"updateFirstLoginHelp": "Update profile on first login",
|
"updateFirstLoginHelp": "Update profile on first login",
|
||||||
|
|
||||||
"nameHelp": "Name of the mapper",
|
|
||||||
"mapperTypeHelp": "",
|
|
||||||
|
|
||||||
"mapperTypeMsadUserAccountControlManagerHelp": "Mapper specific to MSAD. It's able to integrate the MSAD user account state into Keycloak account state (account enabled, password is expired etc). It's using userAccountControl and pwdLastSet MSAD attributes for that. For example if pwdLastSet is 0, the Keycloak user is required to update the password; if userAccountControl is 514 (disabled account) the Keycloak user is disabled as well etc. Mapper is also able to handle the exception code from LDAP user authentication.",
|
"mapperTypeMsadUserAccountControlManagerHelp": "Mapper specific to MSAD. It's able to integrate the MSAD user account state into Keycloak account state (account enabled, password is expired etc). It's using userAccountControl and pwdLastSet MSAD attributes for that. For example if pwdLastSet is 0, the Keycloak user is required to update the password; if userAccountControl is 514 (disabled account) the Keycloak user is disabled as well etc. Mapper is also able to handle the exception code from LDAP user authentication.",
|
||||||
"mapperTypeMsadLdsUserAccountControlMapperHelp": "Mapper specific to MSAD LDS. It's able to integrate the MSAD LDS user account state into Keycloak account state (account enabled, password is expired etc). It's using msDS-UserAccountDisabled and pwdLastSet is 0, the Keycloak user is required to update password, if msDS-UserAccountDisabled is 'TRUE' the Keycloak user is disabled as well etc. Mapper is also able to handle exception code from LDAP user authentication.",
|
"mapperTypeMsadLdsUserAccountControlMapperHelp": "Mapper specific to MSAD LDS. It's able to integrate the MSAD LDS user account state into Keycloak account state (account enabled, password is expired etc). It's using msDS-UserAccountDisabled and pwdLastSet is 0, the Keycloak user is required to update password, if msDS-UserAccountDisabled is 'TRUE' the Keycloak user is disabled as well etc. Mapper is also able to handle exception code from LDAP user authentication.",
|
||||||
"mapperTypeGroupLdapMapperHelp": "Used to map group mappings of groups from some LDAP DN to Keycloak group mappings",
|
"mapperTypeGroupLdapMapperHelp": "Used to map group mappings of groups from some LDAP DN to Keycloak group mappings",
|
||||||
|
@ -83,46 +80,51 @@
|
||||||
|
|
||||||
"passwordPolicyHintsEnabledHelp": "Applicable just for writable MSAD. If on, then updating password of MSAD user will use LDAP_SERVER_POLICY_HINTS_OID extension, which means that advanced MSAD password policies like 'password history' or 'minimal password age' will be applied. This extension works just for MSAD 2008 R2 or newer.",
|
"passwordPolicyHintsEnabledHelp": "Applicable just for writable MSAD. If on, then updating password of MSAD user will use LDAP_SERVER_POLICY_HINTS_OID extension, which means that advanced MSAD password policies like 'password history' or 'minimal password age' will be applied. This extension works just for MSAD 2008 R2 or newer.",
|
||||||
|
|
||||||
"ldapGroupsDnHelp": "LDAP DN where groups of this tree are saved. For example 'ou=groups,dc=example,dc=org'",
|
"nameHelp": "Name of the mapper",
|
||||||
"groupNameLDAPAttributeHelp": "Name of LDAP attribute, which is used in group objects for name and RDN of group. Usually it will be 'cn'. In this case typical group/role object may have DN like 'cn=Group1,ouu=groups,dc=example,dc=org'.",
|
"mapperTypeHelp": "Used to map single attribute from LDAP user to attribute of UserModel in Keycloak DB",
|
||||||
"groupObjectClassesHelp": "Object class (or classes) of the group object. It's divided by commas if more classes needed. In typical LDAP deployment it could be 'groupOfNames'. In Active Directory it's usually 'group'.",
|
|
||||||
"preserveGroupInheritanceHelp": "Flag whether group inheritance from LDAP should be propagated to Keycloak. If false, then all LDAP groups will be mapped as flat top-level groups in Keycloak. Otherwise group inheritance is preserved into Keycloak, but the group sync might fail if LDAP structure contains recursions or multiple parent groups per child groups.",
|
|
||||||
"ignoreMissingGroupsHelp": "Ignore missing groups in the group hierarchy.",
|
|
||||||
"membershipLdapAttributeHelp": "Name of LDAP attribute on group, which is used for membership mappings. Usually it will be 'member'. However when 'Membership Attribute Type' is 'UID', then 'Membership LDAP Attribute' could be typically 'memberUid'.",
|
|
||||||
"membershipAttributeTypeHelp": "DN means that LDAP group has it's members declared in form of their full DN. For example 'member: uid=john,ou=users,dc=example,dc=com'. UID means that LDAP group has it's members declared in form of pure user uids. For example 'memberUid: john'.",
|
|
||||||
"membershipUserLdapAttributeHelp": "Used just if Membership Attribute Type is UID. It is the name of the LDAP attribute on user, which is used for membership mappings. Usually it will be 'uid'. For example if the value of 'Membership User LDAP Attribute' is 'uid' and LDAP group has 'memberUid: john', then it is expected that particular LDAP user will have attribute 'uid: john'.",
|
|
||||||
"ldapFilterHelp": "LDAP Filter adds an additional custom filter to the whole query for retrieve LDAP groups. Leave this empty if no additional filtering is needed and you want to retrieve all groups from LDAP. Otherwise make sure that filter starts with '(' and ends with ')'.",
|
|
||||||
"modeHelp": "LDAP_ONLY means that all group mappings of users are retrieved from LDAP and saved into LDAP. READ_ONLY is Read-only LDAP mode where group mappings are retrieved from both LDAP and DB and merged together. New group joins are not saved to LDAP but to DB. IMPORT is Read-only LDAP mode where group mappings are retrieved from LDAP just at the time when user is imported from LDAP and then they are saved to local keycloak DB.",
|
|
||||||
"userGroupsRetrieveStrategyHelp": "Specify how to retrieve groups of user. LOAD_GROUPS_BY_MEMBER_ATTRIBUTE means that roles of user will be retrieved by sending LDAP query to retrieve all groups where 'member' is our user. GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE means that groups of user will be retrieved from 'memberOf' attribute of our user or from the other attribute specified by 'Member-Of LDAP Attribute'.",
|
|
||||||
"memberofLdapAttributeHelp": "Used just when 'User Roles Retrieve Strategy' is GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE. It specifies the name of the LDAP attribute on the LDAP user, which contains the groups, which the user is member of. Usually it will be the default 'memberOf'.",
|
|
||||||
"mappedGroupAttributesHelp": "List of names of attributes divided by commas. This points to the list of attributes on LDAP group, which will be mapped as attributes of Group in Keycloak. Leave this empty if no additional group attributes are required to be mapped in Keycloak.",
|
|
||||||
"dropNonexistingGroupsDuringSync": "If this flag is true, then during sync of groups from LDAP to Keycloak, we will keep just those Keycloak groups that still exist in LDAP. The rest will be deleted.",
|
|
||||||
"groupsPath": "Keycloak group path the LDAP groups are added to. For example if value '/Applications/App1' is used, then LDAP groups will be available in Keycloak under group 'App1', which is child of top level group 'Applications'. The default value is '/' so LDAP groups will be mapped to the Keycloak groups at the top level. The configured group path must already exist in the Keycloak when creating this mapper.",
|
|
||||||
|
|
||||||
"userModelAttributeHelp": "Name of the UserModel property or attribute you want to map the LDAP attribute into. For example 'firstName', 'lastName, 'email', 'street' etc.",
|
"userModelAttributeHelp": "Name of the UserModel property or attribute you want to map the LDAP attribute into. For example 'firstName', 'lastName, 'email', 'street' etc.",
|
||||||
"ldapAttribute": "Name of mapped attribute on LDAP object. For example 'cn', 'sn', 'mail', 'street', etc.",
|
"ldapAttributeHelp": "Name of mapped attribute on LDAP object. For example 'cn', 'sn', 'mail', 'street', etc.",
|
||||||
"readOnlyHelp": "Read-only attribute is imported from LDAP to UserModel, but it's not saved back to LDAP when user is updated in Keycloak.",
|
"readOnlyHelp": "Read-only attribute is imported from LDAP to UserModel, but it's not saved back to LDAP when user is updated in Keycloak.",
|
||||||
"alwaysReadValueFromLdapHelp": "If on, then during reading of the LDAP attribute value will always used instead of the value from Keycloak DB.",
|
"alwaysReadValueFromLdapHelp": "If on, then during reading of the LDAP attribute value will always used instead of the value from Keycloak DB.",
|
||||||
"isMandatoryInLdapHelp": "If true, attribute is mandatory in LDAP. Hence if there is no value in Keycloak DB, the empty value will be set to be propagated to LDAP.",
|
"isMandatoryInLdapHelp": "If true, attribute is mandatory in LDAP. Hence if there is no value in Keycloak DB, the empty value will be set to be propagated to LDAP.",
|
||||||
"isBinaryAttributeHelp": "Should be true for binary LDAP attributes.",
|
"isBinaryAttributeHelp": "Should be true for binary LDAP attributes.",
|
||||||
|
|
||||||
"ldapRolesDNHelp": "LDAP DN where roles of this tree are saved. For example, 'ou=finance,dc=example,dc=org'",
|
|
||||||
"roleNameLdapAttributeHelp": "Name of LDAP attribute, which is used in role objects for name and RDN of role. Usually it will be 'cn'. In this case typical group/role object may have DN like 'cn=role1,ou=finance,dc=example,dc=org'.",
|
|
||||||
"roleObjectClassesHelp": "Object class (or classes) of the role object. It's divided by commas if more classes are needed. In typical LDAP deployment it could be 'groupOfNames'. In Active Directory it's usually 'group'.",
|
|
||||||
"useRealmRolesMappingHelp": "If true, then LDAP role mappings will be mapped to realm role mappings in Keycloak. Otherwise it will be mapped to client role mappings.",
|
|
||||||
"clientIdHelp": "Client ID of client to which LDAP role mappings will be mapped. Applicable only if 'Use Realm Roles Mapping' is false.",
|
|
||||||
|
|
||||||
"userModelAttributeNameHelp": "Name of the model attribute to be added when importing user from LDAP",
|
|
||||||
"attributeValueHelp": "Value of the model attribute to be added when importing user from LDAP",
|
|
||||||
|
|
||||||
"roleHelp": "Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.",
|
|
||||||
|
|
||||||
"derFormattedHelp": "Activate this if the certificate is DER formatted in LDAP and not PEM formatted.",
|
"derFormattedHelp": "Activate this if the certificate is DER formatted in LDAP and not PEM formatted.",
|
||||||
|
|
||||||
"ldapFullNameAttributeHelp": "Name of LDAP attribute, which contains fullName of user. Usually it will be 'cn',",
|
"ldapFullNameAttributeHelp": "Name of LDAP attribute, which contains fullName of user. Usually it will be 'cn',",
|
||||||
"fullNameLdapMapperReadOnlyHelp": "For Read-only, data is imported from LDAP to Keycloak DB, but it's not saved back to LDAP when user is updated in Keycloak.",
|
"fullNameLdapMapperReadOnlyHelp": "For Read-only, data is imported from LDAP to Keycloak DB, but it's not saved back to LDAP when user is updated in Keycloak.",
|
||||||
"fullNameLdapMapperWriteOnlyHelp": "For Write-only, is data propagated to LDAP when user is created or updated in Keycloak. But this mapper is not used to propagate data from LDAP back into Keycloak. This setting is useful if you configured separate firstName and lastName attribute mappers and you want to use those to read attribute from LDAP into Keycloak",
|
"fullNameLdapMapperWriteOnlyHelp": "For Write-only, is data propagated to LDAP when user is created or updated in Keycloak. But this mapper is not used to propagate data from LDAP back into Keycloak. This setting is useful if you configured separate firstName and lastName attribute mappers and you want to use those to read attribute from LDAP into Keycloak",
|
||||||
|
|
||||||
|
"ldapGroupsDnHelp": "LDAP DN where groups of this tree are saved. For example 'ou=groups,dc=example,dc=org'",
|
||||||
|
"groupNameLdapAttributeHelp": "Name of LDAP attribute, which is used in group objects for name and RDN of group. Usually it will be 'cn'. In this case typical group/role object may have DN like 'cn=Group1,ouu=groups,dc=example,dc=org'.",
|
||||||
|
"groupObjectClassesHelp": "Object class (or classes) of the group object. It's divided by commas if more classes needed. In typical LDAP deployment it could be 'groupOfNames'. In Active Directory it's usually 'group'.",
|
||||||
|
"preserveGroupInheritanceHelp": "Flag whether group inheritance from LDAP should be propagated to Keycloak. If false, then all LDAP groups will be mapped as flat top-level groups in Keycloak. Otherwise group inheritance is preserved into Keycloak, but the group sync might fail if LDAP structure contains recursions or multiple parent groups per child groups.",
|
||||||
|
"ignoreMissingGroupsHelp": "Ignore missing groups in the group hierarchy.",
|
||||||
|
"userGroupsRetrieveStrategyHelp": "Specify how to retrieve groups of user. LOAD_GROUPS_BY_MEMBER_ATTRIBUTE means that roles of user will be retrieved by sending LDAP query to retrieve all groups where 'member' is our user. GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE means that groups of user will be retrieved from 'memberOf' attribute of our user or from the other attribute specified by 'Member-Of LDAP Attribute'.",
|
||||||
|
"mappedGroupAttributesHelp": "List of names of attributes divided by commas. This points to the list of attributes on LDAP group, which will be mapped as attributes of Group in Keycloak. Leave this empty if no additional group attributes are required to be mapped in Keycloak.",
|
||||||
|
"dropNonexistingGroupsDuringSyncHelp": "If this flag is true, then during sync of groups from LDAP to Keycloak, we will keep just those Keycloak groups that still exist in LDAP. The rest will be deleted.",
|
||||||
|
"groupsPathHelp": "Keycloak group path the LDAP groups are added to. For example if value '/Applications/App1' is used, then LDAP groups will be available in Keycloak under group 'App1', which is child of top level group 'Applications'. The default value is '/' so LDAP groups will be mapped to the Keycloak groups at the top level. The configured group path must already exist in the Keycloak when creating this mapper.",
|
||||||
|
|
||||||
|
"ldapRolesDnHelp": "LDAP DN where roles of this tree are saved. For example, 'ou=finance,dc=example,dc=org'",
|
||||||
|
"roleNameLdapAttributeHelp": "Name of LDAP attribute, which is used in role objects for name and RDN of role. Usually it will be 'cn'. In this case typical group/role object may have DN like 'cn=role1,ou=finance,dc=example,dc=org'.",
|
||||||
|
"roleObjectClassesHelp": "Object class (or classes) of the role object. It's divided by commas if more classes are needed. In typical LDAP deployment it could be 'groupOfNames'. In Active Directory it's usually 'group'.",
|
||||||
|
"userRolesRetrieveStrategyHelp": "Specify how to retrieve roles of user. LOAD_ROLES_BY_MEMBER_ATTRIBUTE means that roles fo user will be retrieved by sending LDAP query to retrieve all roles where 'member' is our user. GET_ROLES_FROM_USER_MEMBEROF means that roles of user will be retrieved from 'memberOf' attribute of our user. Or from the other attributes specified by 'Member-Of LDAP Attribute'. LOAD_ROLES_BY_MEMBER_ATTRIBUTE is applicable just in Active Directory and it means that roles of user will be retrieved recursively with usage of LDAP_MATCHING_RULE_IN_CHAIN LDAP extension.",
|
||||||
|
"useRealmRolesMappingHelp": "If true, then LDAP role mappings will be mapped to realm role mappings in Keycloak. Otherwise it will be mapped to client role mappings.",
|
||||||
|
"clientIdHelp": "Client ID of client to which LDAP role mappings will be mapped. Applicable only if 'Use Realm Roles Mapping' is false.",
|
||||||
|
|
||||||
|
"membershipLdapAttributeHelp": "Name of LDAP attribute on group, which is used for membership mappings. Usually it will be 'member'. However when 'Membership Attribute Type' is 'UID', then 'Membership LDAP Attribute' could be typically 'memberUid'.",
|
||||||
|
"membershipAttributeTypeHelp": "DN means that LDAP group has it's members declared in form of their full DN. For example 'member: uid=john,ou=users,dc=example,dc=com'. UID means that LDAP group has it's members declared in form of pure user uids. For example 'memberUid: john'.",
|
||||||
|
"membershipUserLdapAttributeHelp": "Used just if Membership Attribute Type is UID. It is the name of the LDAP attribute on user, which is used for membership mappings. Usually it will be 'uid'. For example if the value of 'Membership User LDAP Attribute' is 'uid' and LDAP group has 'memberUid: john', then it is expected that particular LDAP user will have attribute 'uid: john'.",
|
||||||
|
"ldapFilterHelp": "LDAP Filter adds an additional custom filter to the whole query for retrieve LDAP groups. Leave this empty if no additional filtering is needed and you want to retrieve all groups from LDAP. Otherwise make sure that filter starts with '(' and ends with ')'.",
|
||||||
|
"modeHelp": "LDAP_ONLY means that all group mappings of users are retrieved from LDAP and saved into LDAP. READ_ONLY is Read-only LDAP mode where group mappings are retrieved from both LDAP and DB and merged together. New group joins are not saved to LDAP but to DB. IMPORT is Read-only LDAP mode where group mappings are retrieved from LDAP just at the time when user is imported from LDAP and then they are saved to local keycloak DB.",
|
||||||
|
"memberofLdapAttributeHelp": "Used just when 'User Roles Retrieve Strategy' is GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE. It specifies the name of the LDAP attribute on the LDAP user, which contains the groups, which the user is member of. Usually it will be the default 'memberOf'.",
|
||||||
|
|
||||||
|
"userModelAttributeNameHelp": "Name of the model attribute to be added when importing user from LDAP",
|
||||||
|
"attributeValueHelp": "Value of the model attribute to be added when importing user from LDAP",
|
||||||
|
|
||||||
|
"roleHelp": "Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.",
|
||||||
|
|
||||||
"groupHelp": "Users imported from LDAP will be automatically added into this configured group.",
|
"groupHelp": "Users imported from LDAP will be automatically added into this configured group.",
|
||||||
|
|
||||||
"ldapAttributeNameHelp": "Name of the LDAP attribute, which will be added to the new user during registration",
|
"ldapAttributeNameHelp": "Name of the LDAP attribute, which will be added to the new user during registration",
|
||||||
|
|
|
@ -23,7 +23,7 @@ export const LdapSettingsKerberosIntegration = ({
|
||||||
const allowKerberosAuth: [string] = useWatch({
|
const allowKerberosAuth: [string] = useWatch({
|
||||||
control: form.control,
|
control: form.control,
|
||||||
name: "config.allowKerberosAuthentication",
|
name: "config.allowKerberosAuthentication",
|
||||||
defaultValue: ["true"],
|
defaultValue: ["false"],
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -169,39 +169,38 @@ export const LdapSettingsKerberosIntegration = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={t("debug")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("debugHelp")}
|
||||||
|
forLabel={t("debug")}
|
||||||
|
forID="kc-debug"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-debug"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<Controller
|
||||||
|
name="config.debug"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-debug"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={t("debug")}
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText={helpText("debugHelp")}
|
|
||||||
forLabel={t("debug")}
|
|
||||||
forID="kc-debug"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
fieldId="kc-debug"
|
|
||||||
hasNoPaddingTop
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
<Controller
|
|
||||||
name="config.debug"
|
|
||||||
defaultValue={["false"]}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id={"kc-debug"}
|
|
||||||
isDisabled={false}
|
|
||||||
onChange={(value) => onChange([`${value}`])}
|
|
||||||
isChecked={value[0] === "true"}
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
></Controller>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("useKerberosForPasswordAuthentication")}
|
label={t("useKerberosForPasswordAuthentication")}
|
||||||
labelIcon={
|
labelIcon={
|
||||||
|
|
104
src/user-federation/ldap/mappers/LdapMapperFullNameAttribute.tsx
Normal file
104
src/user-federation/ldap/mappers/LdapMapperFullNameAttribute.tsx
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
import { FormGroup, Switch, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { Controller, UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperFullNameAttributeProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperFullNameAttribute = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperFullNameAttributeProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={t("ldapFullNameAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ldapFullNameAttributeHelp")}
|
||||||
|
forLabel={t("ldapFullNameAttribute")}
|
||||||
|
forID="kc-full-name-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-full-name-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-full-name-attribute"
|
||||||
|
data-testid="full-name-attribute"
|
||||||
|
name="config.ldap-full-name-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("readOnly")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("readOnlyHelp")}
|
||||||
|
forLabel={t("readOnly")}
|
||||||
|
forID="kc-read-only"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-read-only"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.read-only"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-read-only"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("writeOnly")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("writeOnlyHelp")}
|
||||||
|
forLabel={t("writeOnly")}
|
||||||
|
forID="kc-write-only"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-read-only"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.write-only"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-write-only"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { FormGroup, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperHardcodedAttributeProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperHardcodedAttribute = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperHardcodedAttributeProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={t("userModelAttributeName")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("userModelAttributeNameHelp")}
|
||||||
|
forLabel={t("userModelAttributeName")}
|
||||||
|
forID="kc-user-model-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-user-model-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-user-model-attribute"
|
||||||
|
data-testid="user-model-attribute"
|
||||||
|
name="config.user-model-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("attributeValue")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("attributeValueHelp")}
|
||||||
|
forLabel={t("attributeValue")}
|
||||||
|
forID="kc-attribute-value"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-attribute-value"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-attribute-value"
|
||||||
|
data-testid="attribute-value"
|
||||||
|
name="config.attribute-value"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { FormGroup, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperHardcodedLdapAttributeProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperHardcodedLdapAttribute = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperHardcodedLdapAttributeProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={t("ldapAttributeName")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ldapAttributeNameHelp")}
|
||||||
|
forLabel={t("ldapAttributeName")}
|
||||||
|
forID="kc-ldap-attribute-name"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-attribute-name"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-attribute-name"
|
||||||
|
data-testid="ldap-attribute-name"
|
||||||
|
name="config.ldap-attribute-name"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("ldapAttributeValue")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ldapAttributeValueHelp")}
|
||||||
|
forLabel={t("ldapAttributeValue")}
|
||||||
|
forID="kc-ldap-attribute-value"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-attribute-value"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-attribute-value"
|
||||||
|
data-testid="ldap-attribute-value"
|
||||||
|
name="config.ldap-attribute-value"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { FormGroup, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperHardcodedLdapGroupProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperHardcodedLdapGroup = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperHardcodedLdapGroupProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={t("group")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("groupHelp")}
|
||||||
|
forLabel={t("group")}
|
||||||
|
forID="kc-group"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-group"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-group"
|
||||||
|
data-testid="group"
|
||||||
|
name="config.group"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { FormGroup, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperHardcodedLdapRoleProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperHardcodedLdapRole = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperHardcodedLdapRoleProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:role")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("roleHelp")}
|
||||||
|
forLabel={t("common:role")}
|
||||||
|
forID="kc-role"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-role"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-role"
|
||||||
|
data-testid="role"
|
||||||
|
name="config.role"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
149
src/user-federation/ldap/mappers/LdapMapperList.tsx
Normal file
149
src/user-federation/ldap/mappers/LdapMapperList.tsx
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { AlertVariant, Button, ToolbarItem } from "@patternfly/react-core";
|
||||||
|
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||||
|
import { useErrorHandler } from "react-error-boundary";
|
||||||
|
import { KeycloakDataTable } from "../../../components/table-toolbar/KeycloakDataTable";
|
||||||
|
import { ListEmptyState } from "../../../components/list-empty-state/ListEmptyState";
|
||||||
|
import { useAlerts } from "../../../components/alert/Alerts";
|
||||||
|
import {
|
||||||
|
useAdminClient,
|
||||||
|
asyncStateFetch,
|
||||||
|
} from "../../../context/auth/AdminClient";
|
||||||
|
import { Link, useParams, useRouteMatch } from "react-router-dom";
|
||||||
|
|
||||||
|
export const LdapMapperList = () => {
|
||||||
|
const [mappers, setMappers] = useState<ComponentRepresentation[]>();
|
||||||
|
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const adminClient = useAdminClient();
|
||||||
|
const { addAlert } = useAlerts();
|
||||||
|
|
||||||
|
const { url } = useRouteMatch();
|
||||||
|
|
||||||
|
const handleError = useErrorHandler();
|
||||||
|
const [key, setKey] = useState(0);
|
||||||
|
|
||||||
|
const { id } = useParams<{ id: string }>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return asyncStateFetch(
|
||||||
|
() => {
|
||||||
|
const testParams: {
|
||||||
|
[name: string]: string | number;
|
||||||
|
} = {
|
||||||
|
parent: id,
|
||||||
|
type: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper",
|
||||||
|
};
|
||||||
|
return adminClient.components.find(testParams);
|
||||||
|
},
|
||||||
|
(mappers) => {
|
||||||
|
setMappers(mappers);
|
||||||
|
// TODO: remove after debugging
|
||||||
|
console.log("LdapMapperList - setMappers being set with:");
|
||||||
|
console.log(mappers);
|
||||||
|
},
|
||||||
|
handleError
|
||||||
|
);
|
||||||
|
}, [key]);
|
||||||
|
|
||||||
|
if (!mappers) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListEmptyState
|
||||||
|
message={t("common:emptyMappers")}
|
||||||
|
instructions={t("common:emptyMappersInstructions")}
|
||||||
|
primaryActionText={t("common:emptyPrimaryAction")}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const loader = async () =>
|
||||||
|
Promise.resolve(
|
||||||
|
(mappers || []).map((mapper) => {
|
||||||
|
return {
|
||||||
|
...mapper,
|
||||||
|
name: mapper.name,
|
||||||
|
type: mapper.providerId,
|
||||||
|
} as ComponentRepresentation;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const getUrl = (url: string) => {
|
||||||
|
if (url.indexOf("/mappers") === -1) {
|
||||||
|
return `${url}/mappers`;
|
||||||
|
}
|
||||||
|
return `${url}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MapperLink = (mapper: ComponentRepresentation) => (
|
||||||
|
<>
|
||||||
|
<Link to={`${getUrl(url)}/${mapper.id}`}>{mapper.name}</Link>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<KeycloakDataTable
|
||||||
|
key={key}
|
||||||
|
loader={loader}
|
||||||
|
ariaLabelKey="ldapMappersList"
|
||||||
|
searchPlaceholderKey="common:searchForMapper"
|
||||||
|
toolbarItem={
|
||||||
|
<ToolbarItem>
|
||||||
|
<Button
|
||||||
|
data-testid="createMapperBtn"
|
||||||
|
variant="primary"
|
||||||
|
// onClick={handleModalToggle}
|
||||||
|
onClick={() =>
|
||||||
|
addAlert(
|
||||||
|
t("Add functionality not implemented yet!"),
|
||||||
|
AlertVariant.success
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("common:addMapper")}
|
||||||
|
</Button>
|
||||||
|
</ToolbarItem>
|
||||||
|
}
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
title: t("common:delete"),
|
||||||
|
onRowClick: async (mapper) => {
|
||||||
|
try {
|
||||||
|
addAlert(
|
||||||
|
// t("common:mappingDeletedError"),
|
||||||
|
"Delete functionality not implemented yet!",
|
||||||
|
AlertVariant.success
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
addAlert(
|
||||||
|
t("common:mappingDeletedError", { error }),
|
||||||
|
AlertVariant.danger
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
cellRenderer: MapperLink,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "type",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
emptyState={
|
||||||
|
<ListEmptyState
|
||||||
|
message={t("common:emptyMappers")}
|
||||||
|
instructions={t("common:emptyMappersInstructions")}
|
||||||
|
primaryActionText={t("common:emptyPrimaryAction")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperMsadLdsUserAccountProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperMsadLdsUserAccount = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperMsadLdsUserAccountProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { FormGroup, Switch } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { Controller, UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperMsadUserAccountProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperMsadUserAccount = ({
|
||||||
|
form,
|
||||||
|
}: LdapMapperMsadUserAccountProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={t("passwordPolicyHintsEnabled")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("passwordPolicyHintsEnabledHelp")}
|
||||||
|
forLabel={t("passwordPolicyHintsEnabled")}
|
||||||
|
forID="kc-pw-policy-hints-enabled"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-der-formatted"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.ldap-password-policy-hints-enabled"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-pw-policy-hints-enabled"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
571
src/user-federation/ldap/mappers/LdapMapperRoleGroup.tsx
Normal file
571
src/user-federation/ldap/mappers/LdapMapperRoleGroup.tsx
Normal file
|
@ -0,0 +1,571 @@
|
||||||
|
import {
|
||||||
|
FormGroup,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
SelectVariant,
|
||||||
|
Switch,
|
||||||
|
TextInput,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { Controller, UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperRoleGroupProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperRoleGroup = ({
|
||||||
|
form,
|
||||||
|
type,
|
||||||
|
}: LdapMapperRoleGroupProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
const [isMbAttTypeDropdownOpen, setIsMbAttTypeDropdownOpen] = useState(false);
|
||||||
|
const [isModeDropdownOpen, setIsModeDropdownOpen] = useState(false);
|
||||||
|
const [
|
||||||
|
isRetrieveStratDropdownOpen,
|
||||||
|
setIsRetrieveStratDropdownOpen,
|
||||||
|
] = useState(false);
|
||||||
|
const [isClientIdDropdownOpen, setIsClientIdDropdownOpen] = useState(false);
|
||||||
|
|
||||||
|
let isRole = true;
|
||||||
|
const groupMapper = "group-ldap-mapper";
|
||||||
|
|
||||||
|
if (type === groupMapper) {
|
||||||
|
isRole = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={isRole ? t("ldapRolesDn") : t("ldapGroupsDn")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={
|
||||||
|
isRole
|
||||||
|
? helpText("ldapRolesDnHelp")
|
||||||
|
: helpText("ldapGroupsDnHelp")
|
||||||
|
}
|
||||||
|
forLabel={isRole ? t("ldapRolesDN") : t("ldapGroupsDN")}
|
||||||
|
forID="kc-ldap-dn"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-dn"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-dn"
|
||||||
|
data-testid="ldap-dn"
|
||||||
|
name={isRole ? "config.roles-dn" : "config.groups-dn"}
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={
|
||||||
|
isRole ? t("roleNameLdapAttribute") : t("groupNameLdapAttribute")
|
||||||
|
}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={
|
||||||
|
isRole
|
||||||
|
? helpText("roleNameLdapAttributeHelp")
|
||||||
|
: helpText("groupNameLdapAttributeHelp")
|
||||||
|
}
|
||||||
|
forLabel={
|
||||||
|
isRole ? t("roleNameLdapAttribute") : t("roleNameLdapAttribute")
|
||||||
|
}
|
||||||
|
forID="kc-name-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-name-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-name-attribute"
|
||||||
|
data-testid="name-attribute"
|
||||||
|
name={
|
||||||
|
isRole
|
||||||
|
? "config.role-name-ldap-attribute"
|
||||||
|
: "config.group-name-ldap-attribute"
|
||||||
|
}
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={isRole ? t("roleObjectClasses") : t("groupObjectClasses")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={
|
||||||
|
isRole
|
||||||
|
? helpText("roleObjectClassesHelp")
|
||||||
|
: helpText("groupObjectClassesHelp")
|
||||||
|
}
|
||||||
|
forLabel={
|
||||||
|
isRole ? t("roleObjectClasses") : t("groupObjectClasses")
|
||||||
|
}
|
||||||
|
forID="kc-object-classes"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-object-classes"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-object-classes"
|
||||||
|
data-testid="object-classes"
|
||||||
|
name={
|
||||||
|
isRole
|
||||||
|
? "config.role-object-classes"
|
||||||
|
: "config.group-object-classes"
|
||||||
|
}
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{!isRole && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("preserveGroupInheritance")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("preserveGroupInheritanceHelp")}
|
||||||
|
forLabel={t("preserveGroupInheritance")}
|
||||||
|
forID="kc-preserve-inheritance"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-preserve-inheritance"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.preserve-group-inheritance"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-preserve-inheritance"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("ignoreMissingGroups")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ignoreMissingGroupsHelp")}
|
||||||
|
forLabel={t("ignoreMissingGroups")}
|
||||||
|
forID="kc-ignore-missing"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ignore-missing"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.ignore-missing-groups"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-ignore-missing"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<FormGroup
|
||||||
|
label={t("membershipLdapAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("membershipLdapAttributeHelp")}
|
||||||
|
forLabel={t("membershipLdapAttribute")}
|
||||||
|
forID="kc-membership-ldap-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-membership-ldap-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-membership-ldap-attribute"
|
||||||
|
data-testid="membership-ldap-attribute"
|
||||||
|
name="config.membership-ldap-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("membershipAttributeType")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("membershipAttributeTypeHelp")}
|
||||||
|
forLabel={t("membershipAttributeType")}
|
||||||
|
forID="kc-membership-attribute-type"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-membership-attribute-type"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.membership-attribute-type[0]"
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-membership-attribute-type"
|
||||||
|
onToggle={() =>
|
||||||
|
setIsMbAttTypeDropdownOpen(!isMbAttTypeDropdownOpen)
|
||||||
|
}
|
||||||
|
isOpen={isMbAttTypeDropdownOpen}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setIsMbAttTypeDropdownOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
>
|
||||||
|
<SelectOption key={0} value="DN">
|
||||||
|
DN
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption key={1} value="UID">
|
||||||
|
UID
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("membershipUserLdapAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("membershipUserLdapAttributeHelp")}
|
||||||
|
forLabel={t("membershipUserLdapAttribute")}
|
||||||
|
forID="kc-membership-user-ldap-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-membership-user-ldap-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-membership-user-ldap-attribute"
|
||||||
|
data-testid="membership-user-ldap-attribute"
|
||||||
|
name="config.membership-user-ldap-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("ldapFilter")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ldapFilterHelp")}
|
||||||
|
forLabel={t("ldapFilter")}
|
||||||
|
forID="kc-ldap-filter"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-filter"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-filter"
|
||||||
|
data-testid="ldap-filter"
|
||||||
|
name="config.ldap-filter"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("mode")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("modeHelp")}
|
||||||
|
forLabel={t("mode")}
|
||||||
|
forID="kc-mode"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-mode"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.mode[0]"
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-mode"
|
||||||
|
onToggle={() => setIsModeDropdownOpen(!isModeDropdownOpen)}
|
||||||
|
isOpen={isModeDropdownOpen}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setIsModeDropdownOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
>
|
||||||
|
<SelectOption key={0} value="READ_ONLY">
|
||||||
|
READ_ONLY
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption key={1} value="LDAP_ONLY">
|
||||||
|
LDAP_ONLY
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption key={2} value="IMPORT">
|
||||||
|
IMPORT
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={
|
||||||
|
isRole
|
||||||
|
? t("userRolesRetrieveStrategy")
|
||||||
|
: t("userGroupsRetrieveStrategy")
|
||||||
|
}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={
|
||||||
|
isRole
|
||||||
|
? helpText("userRolesRetrieveStrategyHelp")
|
||||||
|
: helpText("userGroupsRetrieveStrategyHelp")
|
||||||
|
}
|
||||||
|
forLabel={
|
||||||
|
isRole
|
||||||
|
? t("userRolesRetrieveStrategy")
|
||||||
|
: t("userGroupsRetrieveStrategy")
|
||||||
|
}
|
||||||
|
forID="kc-user-retrieve-strategy"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-user-retrieve-strategy"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name={
|
||||||
|
isRole
|
||||||
|
? "config.user-roles-retrieve-strategy[0]"
|
||||||
|
: "config.user-groups-retrieve-strategy[0]"
|
||||||
|
}
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-user-retrieve-strategy"
|
||||||
|
onToggle={() =>
|
||||||
|
setIsRetrieveStratDropdownOpen(!isRetrieveStratDropdownOpen)
|
||||||
|
}
|
||||||
|
isOpen={isRetrieveStratDropdownOpen}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setIsRetrieveStratDropdownOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
>
|
||||||
|
<SelectOption key={0} value="LOAD_ROLES_BY_MEMBER_ATTRIBUTE">
|
||||||
|
LOAD_ROLES_BY_MEMBER_ATTRIBUTE
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption
|
||||||
|
key={1}
|
||||||
|
value="GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE"
|
||||||
|
>
|
||||||
|
GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption
|
||||||
|
key={2}
|
||||||
|
value="LOAD_ROLES_BY_MEMBER_ATTRIBUTE_RECURSIVELY"
|
||||||
|
>
|
||||||
|
LOAD_ROLES_BY_MEMBER_ATTRIBUTE_RECURSIVELY
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("memberofLdapAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("memberofLdapAttributeHelp")}
|
||||||
|
forLabel={t("memberofLdapAttribute")}
|
||||||
|
forID="kc-member-of-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-member-of-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-member-of-attribute"
|
||||||
|
data-testid="member-of-attribute"
|
||||||
|
name="config.memberof-ldap-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{isRole && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("useRealmRolesMapping")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("useRealmRolesMappingHelp")}
|
||||||
|
forLabel={t("useRealmRolesMapping")}
|
||||||
|
forID="kc-use-realm-roles"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-use-realm-roles"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.use-realm-roles-mapping"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-use-realm-roles"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:clientId")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("clientIdHelp")}
|
||||||
|
forLabel={t("common:clientId")}
|
||||||
|
forID="kc-client-id"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-client-id"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.client-id[0]"
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-client-id"
|
||||||
|
onToggle={() =>
|
||||||
|
setIsClientIdDropdownOpen(!isClientIdDropdownOpen)
|
||||||
|
}
|
||||||
|
isOpen={isClientIdDropdownOpen}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setIsClientIdDropdownOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
>
|
||||||
|
<SelectOption key={0} value="account">
|
||||||
|
Need to fetch clients here
|
||||||
|
</SelectOption>
|
||||||
|
<SelectOption key={1} value="admin-cli">
|
||||||
|
These are placeholders
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!isRole && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("mappedGroupAttributes")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("mappedGroupAttributesHelp")}
|
||||||
|
forLabel={t("mappedGroupAttributes")}
|
||||||
|
forID="kc-mapped-attributes"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-mapped-attributes"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-mapped-attributes"
|
||||||
|
data-testid="mapped-attributes"
|
||||||
|
name="config.mapped-group-attributes"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("dropNonexistingGroupsDuringSync")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("dropNonexistingGroupsDuringSyncHelp")}
|
||||||
|
forLabel={t("dropNonexistingGroupsDuringSync")}
|
||||||
|
forID="kc-drop-nonexisting"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-drop-nonexisting"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.drop-non-existing-groups-during-sync"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-drop-nonexisting"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("groupsPath")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("groupsPathHelp")}
|
||||||
|
forLabel={t("groupsPath")}
|
||||||
|
forID="kc-path"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-path"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-path"
|
||||||
|
data-testid="path"
|
||||||
|
name="config.groups-path"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
216
src/user-federation/ldap/mappers/LdapMapperUserAttribute.tsx
Normal file
216
src/user-federation/ldap/mappers/LdapMapperUserAttribute.tsx
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
import { FormGroup, Switch, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
import { Controller, UseFormMethods } from "react-hook-form";
|
||||||
|
import { FormAccess } from "../../../components/form-access/FormAccess";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LdapMapperGeneral } from "./shared/LdapMapperGeneral";
|
||||||
|
|
||||||
|
export type LdapMapperUserAttributeProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
mapperType: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperUserAttribute = ({
|
||||||
|
form,
|
||||||
|
mapperType,
|
||||||
|
}: LdapMapperUserAttributeProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormAccess role="manage-realm" isHorizontal>
|
||||||
|
<LdapMapperGeneral form={form} />
|
||||||
|
<FormGroup
|
||||||
|
label={t("userModelAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("userModelAttributeHelp")}
|
||||||
|
forLabel={t("userModelAttribute")}
|
||||||
|
forID="kc-user-model-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-user-model-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-user-model-attribute"
|
||||||
|
data-testid="user-model-attribute"
|
||||||
|
name="config.user-model-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("ldapAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("ldapAttributeHelp")}
|
||||||
|
forLabel={t("ldapAttribute")}
|
||||||
|
forID="kc-ldap-attribute"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-attribute"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-attribute"
|
||||||
|
data-testid="ldap-attribute"
|
||||||
|
name="config.ldap-attribute"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("readOnly")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("readOnlyHelp")}
|
||||||
|
forLabel={t("readOnly")}
|
||||||
|
forID="kc-read-only"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-read-only"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.read-only"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-read-only"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("alwaysReadValueFromLdap")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("alwaysReadValueFromLdapHelp")}
|
||||||
|
forLabel={t("alwaysReadValueFromLdap")}
|
||||||
|
forID="kc-always-read-value"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-always-read-value"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.always-read-value-from-ldap"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-always-read-value"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("isMandatoryInLdap")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("isMandatoryInLdapHelp")}
|
||||||
|
forLabel={t("isMandatoryInLdap")}
|
||||||
|
forID="kc-is-mandatory"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-is-mandatory"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.is-mandatory-in-ldap"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-is-mandatory"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("isBinaryAttribute")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("isBinaryAttributeHelp")}
|
||||||
|
forLabel={t("isBinaryAttribute")}
|
||||||
|
forID="kc-is-binary"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-is-binary"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.is-binary-attribute"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-is-binary"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
{mapperType === "certificate-ldap-mapper" ? (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("derFormatted")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("derFormattedHelp")}
|
||||||
|
forLabel={t("derFormatted")}
|
||||||
|
forID="kc-der-formatted"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-der-formatted"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.is-der-formatted"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-der-formatted"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
></Controller>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</FormAccess>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
164
src/user-federation/ldap/mappers/LdapMappingDetails.tsx
Normal file
164
src/user-federation/ldap/mappers/LdapMappingDetails.tsx
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
ActionGroup,
|
||||||
|
AlertVariant,
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
PageSection,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
import { convertToFormValues } from "../../../util";
|
||||||
|
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||||
|
import { useAdminClient } from "../../../context/auth/AdminClient";
|
||||||
|
import { ViewHeader } from "../../../components/view-header/ViewHeader";
|
||||||
|
import { useHistory, useParams } from "react-router-dom";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useAlerts } from "../../../components/alert/Alerts";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { LdapMapperUserAttribute } from "./LdapMapperUserAttribute";
|
||||||
|
import { LdapMapperMsadUserAccount } from "./LdapMapperMsadUserAccount";
|
||||||
|
import { LdapMapperMsadLdsUserAccount } from "./LdapMapperMsadLdsUserAccount";
|
||||||
|
import { LdapMapperFullNameAttribute } from "./LdapMapperFullNameAttribute";
|
||||||
|
|
||||||
|
import { LdapMapperHardcodedLdapRole } from "./LdapMapperHardcodedLdapRole";
|
||||||
|
import { LdapMapperHardcodedLdapGroup } from "./LdapMapperHardcodedLdapGroup";
|
||||||
|
import { LdapMapperHardcodedLdapAttribute } from "./LdapMapperHardcodedLdapAttribute";
|
||||||
|
import { LdapMapperHardcodedAttribute } from "./LdapMapperHardcodedAttribute";
|
||||||
|
|
||||||
|
import { LdapMapperRoleGroup } from "./LdapMapperRoleGroup";
|
||||||
|
|
||||||
|
import { useRealm } from "../../../context/realm-context/RealmContext";
|
||||||
|
|
||||||
|
export const LdapMappingDetails = () => {
|
||||||
|
const form = useForm<ComponentRepresentation>();
|
||||||
|
const [mapper, setMapper] = useState<ComponentRepresentation>();
|
||||||
|
|
||||||
|
const adminClient = useAdminClient();
|
||||||
|
const { mapperId } = useParams<{ mapperId: string }>();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const { realm } = useRealm();
|
||||||
|
const id = mapperId;
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const { addAlert } = useAlerts();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (mapperId) {
|
||||||
|
const fetchedMapper = await adminClient.components.findOne({ id });
|
||||||
|
if (fetchedMapper) {
|
||||||
|
// TODO: remove after adding all mapper types
|
||||||
|
console.log("LdapMappingDetails: id used in findOne(id) call::");
|
||||||
|
console.log(id);
|
||||||
|
console.log("LdapMappingDetails: data returned from findOne(id):");
|
||||||
|
console.log(fetchedMapper);
|
||||||
|
setMapper(fetchedMapper);
|
||||||
|
setupForm(fetchedMapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setupForm = (mapper: ComponentRepresentation) => {
|
||||||
|
Object.entries(mapper).map((entry) => {
|
||||||
|
if (entry[0] === "config") {
|
||||||
|
convertToFormValues(entry[1], "config", form.setValue);
|
||||||
|
} else {
|
||||||
|
form.setValue(entry[0], entry[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
addAlert(
|
||||||
|
t(
|
||||||
|
id === "new"
|
||||||
|
? "Create functionality not implemented yet!"
|
||||||
|
: "Save functionality not implemented yet!"
|
||||||
|
),
|
||||||
|
AlertVariant.success
|
||||||
|
);
|
||||||
|
history.push(`/${realm}/user-federation`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewHeader titleKey={mapper ? mapper.name! : ""} subKey="" />
|
||||||
|
<PageSection variant="light" isFilled>
|
||||||
|
{mapper
|
||||||
|
? (mapper.providerId! === "certificate-ldap-mapper" ||
|
||||||
|
mapper.providerId! === "user-attribute-ldap-mapper") && (
|
||||||
|
<LdapMapperUserAttribute
|
||||||
|
form={form}
|
||||||
|
mapperType={mapper?.providerId}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "msad-user-account-control-mapper" && (
|
||||||
|
<LdapMapperMsadUserAccount form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "msad-lds-user-account-control-mapper" && (
|
||||||
|
<LdapMapperMsadLdsUserAccount form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "full-name-ldap-mapper" && (
|
||||||
|
<LdapMapperFullNameAttribute form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "hardcoded-ldap-role-mapper" && (
|
||||||
|
<LdapMapperHardcodedLdapRole form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "hardcoded-ldap-group-mapper" && (
|
||||||
|
<LdapMapperHardcodedLdapGroup form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "hardcoded-ldap-attribute-mapper" && (
|
||||||
|
<LdapMapperHardcodedLdapAttribute form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? mapper.providerId! === "hardcoded-attribute-mapper" && (
|
||||||
|
<LdapMapperHardcodedAttribute form={form} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
{mapper
|
||||||
|
? (mapper.providerId! === "role-ldap-mapper" ||
|
||||||
|
mapper.providerId! === "group-ldap-mapper") && (
|
||||||
|
<LdapMapperRoleGroup form={form} type={mapper.providerId} />
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
<Form onSubmit={form.handleSubmit(save)}>
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
isDisabled={!form.formState.isDirty}
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
data-testid="ldap-save"
|
||||||
|
>
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="link"
|
||||||
|
onClick={() =>
|
||||||
|
history.push(
|
||||||
|
`/${realm}/user-federation/ldap/${mapper!.parentId}/mappers`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
data-testid="ldap-cancel"
|
||||||
|
>
|
||||||
|
{t("common:cancel")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</Form>
|
||||||
|
</PageSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { FormGroup, TextInput } from "@patternfly/react-core";
|
||||||
|
import React from "react";
|
||||||
|
import { HelpItem } from "../../../../components/help-enabler/HelpItem";
|
||||||
|
import { UseFormMethods } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
export type LdapMapperGeneralProps = {
|
||||||
|
form: UseFormMethods;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LdapMapperGeneral = ({ form }: LdapMapperGeneralProps) => {
|
||||||
|
const { t } = useTranslation("user-federation");
|
||||||
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormGroup label={t("common:id")} fieldId="kc-ldap-mapper-id">
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-mapper-id"
|
||||||
|
data-testid="ldap-mapper-id"
|
||||||
|
name="id"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:name")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("nameHelp")}
|
||||||
|
forLabel={t("common:name")}
|
||||||
|
forID="kc-ldap-mapper-name"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-mapper-name"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-mapper-name"
|
||||||
|
data-testid="ldap-mapper-name"
|
||||||
|
name="name"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:mapperType")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={helpText("mapperTypeHelp")}
|
||||||
|
forLabel={t("common:mapperType")}
|
||||||
|
forID="kc-ldap-mapper-type"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-ldap-mapper-type"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-ldap-mapper-type"
|
||||||
|
data-testid="ldap-mapper-type"
|
||||||
|
name="providerId"
|
||||||
|
ref={form.register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -119,8 +119,6 @@
|
||||||
"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)",
|
"validateCustomUserSearchFilter": "Filter must be enclosed in parentheses, for example: (filter)",
|
||||||
|
|
||||||
"id": "ID",
|
|
||||||
"mapperType": "Mapper type",
|
|
||||||
"mapperTypeMsadUserAccountControlManager": "msad-user-account-control-mapper",
|
"mapperTypeMsadUserAccountControlManager": "msad-user-account-control-mapper",
|
||||||
"mapperTypeMsadLdsUserAccountControlMapper": "msad-user-account-control-mapper",
|
"mapperTypeMsadLdsUserAccountControlMapper": "msad-user-account-control-mapper",
|
||||||
"mapperTypeGroupLdapMapper": "group-ldap-mapper",
|
"mapperTypeGroupLdapMapper": "group-ldap-mapper",
|
||||||
|
@ -133,23 +131,36 @@
|
||||||
"mapperTypeHardcodedLdapGroupMapper": "hardcoded-ldap-group-mapper",
|
"mapperTypeHardcodedLdapGroupMapper": "hardcoded-ldap-group-mapper",
|
||||||
"mapperTypeLdapAttributeMapper": "hardcoded-ldap-attribute-mapper",
|
"mapperTypeLdapAttributeMapper": "hardcoded-ldap-attribute-mapper",
|
||||||
|
|
||||||
"passwordPolicyHintsEnabled": "Password policy hints enabled",
|
"ldapMappersList": "LDAP Mappers",
|
||||||
|
|
||||||
|
"ldapFullNameAttribute": "LDAP full name attribute",
|
||||||
|
"writeOnly": "Write only",
|
||||||
|
|
||||||
"ldapGroupsDn": "LDAP Groups DN",
|
"ldapGroupsDn": "LDAP groups DN",
|
||||||
"groupNameLDAPAttribute": "Group name LDAP attribute",
|
"groupNameLdapAttribute": "Group name LDAP attribute",
|
||||||
"groupObjectClasses": "Group object classes",
|
"groupObjectClasses": "Group object classes",
|
||||||
"preserveGroupInheritance": "Preserve group inheritance",
|
"preserveGroupInheritance": "Preserve group inheritance",
|
||||||
"ignoreMissingGroups": "Ignore missing groups",
|
"ignoreMissingGroups": "Ignore missing groups",
|
||||||
|
"userGroupsRetrieveStrategy": "User groups retrieve strategy",
|
||||||
|
"mappedGroupAttributes": "Mapped group attributes",
|
||||||
|
"dropNonexistingGroupsDuringSync": "Drop non-existing groups during sync",
|
||||||
|
"groupsPath": "Groups path",
|
||||||
|
|
||||||
"membershipLdapAttribute": "Membership LDAP attribute",
|
"membershipLdapAttribute": "Membership LDAP attribute",
|
||||||
"membershipAttributeType": "Membership attribute type",
|
"membershipAttributeType": "Membership attribute type",
|
||||||
"membershipUserLdapAttribute": "Membership user LDAP attribute",
|
"membershipUserLdapAttribute": "Membership user LDAP attribute",
|
||||||
"ldapFilter": "LDAP filter",
|
"ldapFilter": "LDAP filter",
|
||||||
"mode": "Mode",
|
"mode": "Mode",
|
||||||
"userGroupsRetrieveStrategy": "User groups retrieve strategy",
|
|
||||||
"memberofLdapAttribute": "Member-of LDAP attribute",
|
"memberofLdapAttribute": "Member-of LDAP attribute",
|
||||||
"mappedGroupAttributes": "Mapped group attributes",
|
|
||||||
"dropNonexistingGroupsDuringSync": "Drop non-existing groups during sync",
|
"ldapRolesDn": "LDAP roles DN",
|
||||||
"groupsPath": "Groups path",
|
"roleNameLdapAttribute": "Role name LDAP attribute",
|
||||||
|
"roleObjectClasses": "Role object classes",
|
||||||
|
"userRolesRetrieveStrategy": "User roles retrieve strategy",
|
||||||
|
"useRealmRolesMapping": "Use realm roles mapping",
|
||||||
|
|
||||||
|
"ldapAttributeName": "LDAP attribute name",
|
||||||
|
"ldapAttributeValue": "LDAP attribute value",
|
||||||
|
|
||||||
"userModelAttribute": "User model attribute",
|
"userModelAttribute": "User model attribute",
|
||||||
"ldapAttribute": "LDAP attribute",
|
"ldapAttribute": "LDAP attribute",
|
||||||
|
@ -157,21 +168,15 @@
|
||||||
"alwaysReadValueFromLdap": "Always read value from LDAP",
|
"alwaysReadValueFromLdap": "Always read value from LDAP",
|
||||||
"isMandatoryInLdap": "Is mandatory in LDAP",
|
"isMandatoryInLdap": "Is mandatory in LDAP",
|
||||||
"isBinaryAttribute": "Is binary attribute",
|
"isBinaryAttribute": "Is binary attribute",
|
||||||
|
|
||||||
"ldapRolesDN": "LDAP roles DN",
|
|
||||||
"roleNameLdapAttribute": "Role Name LDAP attribute",
|
|
||||||
"roleObjectClasses": "Role object classes",
|
|
||||||
"useRealmRolesMapping": "Use realm roles mapping",
|
|
||||||
"clientId": "Client ID",
|
|
||||||
|
|
||||||
"derFormatted": "DER formatted",
|
"derFormatted": "DER formatted",
|
||||||
|
|
||||||
"ldapFullNameAttribute": "LDAP full name attribute",
|
"passwordPolicyHintsEnabled": "Password policy hints enabled",
|
||||||
"writeOnly": "Write only",
|
|
||||||
|
|
||||||
"group": "Group",
|
"userModelAttributeName": "User model attribute name",
|
||||||
|
"attributeValue": "Attribute value",
|
||||||
|
|
||||||
"ldapAttributeName": "LDAP attribute name",
|
"selectRole": "Select role",
|
||||||
"ldapAttributeValue": "LDAP attribute value"
|
|
||||||
|
"group": "Group"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ export const UserForm = ({
|
||||||
{editMode ? (
|
{editMode ? (
|
||||||
<>
|
<>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("id")}
|
label={t("common:id")}
|
||||||
fieldId="kc-id"
|
fieldId="kc-id"
|
||||||
isRequired
|
isRequired
|
||||||
validated={errors.id ? "error" : "default"}
|
validated={errors.id ? "error" : "default"}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
"removedGroupMembershipError": "Error removing group membership",
|
"removedGroupMembershipError": "Error removing group membership",
|
||||||
"path": "Path",
|
"path": "Path",
|
||||||
"emptyInstructions": "Change your search criteria or add a user",
|
"emptyInstructions": "Change your search criteria or add a user",
|
||||||
"id": "ID",
|
|
||||||
"createdAt": "Created at",
|
"createdAt": "Created at",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
|
|
Loading…
Reference in a new issue