UNPKG

@keycloakify/keycloak-admin-ui

Version:
351 lines 19.3 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { KeycloakDataTable, ScrollForm, useAlerts, useFetch, } from "../../ui-shared"; import { AlertVariant, Button, ButtonVariant, Divider, DropdownItem, Form, PageSection, Tab, TabTitleText, ToolbarItem, } from "@patternfly/react-core"; import { useMemo, useState } from "react"; import { Controller, FormProvider, useForm, useFormContext, useWatch, } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Link, useNavigate } from "react-router-dom"; import { useAdminClient } from "../../admin-client"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup"; import { FormAccess } from "../../components/form/FormAccess"; import { KeycloakSpinner } from "../../ui-shared"; import { ListEmptyState } from "../../ui-shared"; import { PermissionsTab } from "../../components/permission-tab/PermissionTab"; import { RoutableTabs, useRoutableTab, } from "../../components/routable-tabs/RoutableTabs"; import { ViewHeader } from "../../components/view-header/ViewHeader"; import { useRealm } from "../../context/realm-context/RealmContext"; import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; import { toUpperCase } from "../../util"; import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled"; import { useParams } from "../../utils/useParams"; import { toIdentityProviderAddMapper } from "../../identity-providers/routes/AddMapper"; import { toIdentityProviderEditMapper } from "../../identity-providers/routes/EditMapper"; import { toIdentityProvider, } from "../../identity-providers/routes/IdentityProvider"; import { toIdentityProviders } from "../../identity-providers/routes/IdentityProviders"; import { AdvancedSettings } from "../../identity-providers/add/AdvancedSettings"; import { DescriptorSettings } from "../../identity-providers/add/DescriptorSettings"; import { DiscoverySettings } from "../../identity-providers/add/DiscoverySettings"; import { ExtendedNonDiscoverySettings } from "../../identity-providers/add/ExtendedNonDiscoverySettings"; import { GeneralSettings } from "../../identity-providers/add/GeneralSettings"; import { OIDCAuthentication } from "../../identity-providers/add/OIDCAuthentication"; import { OIDCGeneralSettings } from "../../identity-providers/add/OIDCGeneralSettings"; import { ReqAuthnConstraints } from "../../identity-providers/add/ReqAuthnConstraintsSettings"; import { SamlGeneralSettings } from "../../identity-providers/add/SamlGeneralSettings"; const Header = ({ onChange, value, save, toggleDeleteDialog }) => { var _a, _b; const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { alias: displayName } = useParams(); const [provider, setProvider] = useState(); const { addAlert, addError } = useAlerts(); const { setValue, formState, control } = useFormContext(); const validateSignature = useWatch({ control, name: "config.validateSignature", }); const useMetadataDescriptorUrl = useWatch({ control, name: "config.useMetadataDescriptorUrl", }); const metadataDescriptorUrl = useWatch({ control, name: "config.metadataDescriptorUrl", }); useFetch(() => adminClient.identityProviders.findOne({ alias: displayName }), (fetchedProvider) => { if (!fetchedProvider) { throw new Error(t("notFound")); } setProvider(fetchedProvider); }, []); const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({ titleKey: "disableProvider", messageKey: t("disableConfirmIdentityProvider", { provider: displayName }), continueButtonLabel: "disable", onConfirm: () => { onChange(!value); save(); }, }); const importSamlKeys = async (providerId, metadataDescriptorUrl) => { try { const result = await adminClient.identityProviders.importFromUrl({ providerId: providerId, fromUrl: metadataDescriptorUrl, }); if (result.signingCertificate) { setValue(`config.signingCertificate`, result.signingCertificate); addAlert(t("importKeysSuccess"), AlertVariant.success); } else { addError("importKeysError", t("importKeysErrorNoSigningCertificate")); } } catch (error) { addError("importKeysError", error); } }; const reloadSamlKeys = async (alias) => { try { const result = await adminClient.identityProviders.reloadKeys({ alias: alias, }); if (result) { addAlert(t("reloadKeysSuccess"), AlertVariant.success); } else { addAlert(t("reloadKeysSuccessButFalse"), AlertVariant.warning); } } catch (error) { addError("reloadKeysError", error); } }; return (_jsxs(_Fragment, { children: [_jsx(DisableConfirm, {}), _jsx(ViewHeader, { titleKey: toUpperCase(provider ? provider.displayName ? provider.displayName : provider.providerId : ""), divider: false, dropdownItems: [ ...(((_a = provider === null || provider === void 0 ? void 0 : provider.providerId) === null || _a === void 0 ? void 0 : _a.includes("saml")) && validateSignature === "true" && useMetadataDescriptorUrl === "true" && metadataDescriptorUrl && !formState.isDirty && value ? [ _jsx(DropdownItem, { onClick: () => reloadSamlKeys(provider.alias), children: t("reloadKeys") }, "reloadKeys"), ] : ((_b = provider === null || provider === void 0 ? void 0 : provider.providerId) === null || _b === void 0 ? void 0 : _b.includes("saml")) && validateSignature === "true" && useMetadataDescriptorUrl !== "true" && metadataDescriptorUrl && !formState.isDirty ? [ _jsx(DropdownItem, { onClick: () => importSamlKeys(provider.providerId, metadataDescriptorUrl), children: t("importKeys") }, "importKeys"), ] : []), _jsx(Divider, {}, "separator"), _jsx(DropdownItem, { onClick: () => toggleDeleteDialog(), children: t("delete") }, "delete"), ], isEnabled: value, onToggle: (value) => { if (!value) { toggleDisableDialog(); } else { onChange(value); save(); } } })] })); }; const MapperLink = ({ name, mapperId, provider }) => { const { realm } = useRealm(); const { alias } = useParams(); return (_jsx(Link, { to: toIdentityProviderEditMapper({ realm, alias, providerId: provider === null || provider === void 0 ? void 0 : provider.providerId, id: mapperId, }), children: name })); }; export default function DetailSettings() { const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { alias, providerId } = useParams(); const isFeatureEnabled = useIsFeatureEnabled(); const form = useForm(); const { handleSubmit, getValues, reset } = form; const [provider, setProvider] = useState(); const [selectedMapper, setSelectedMapper] = useState(); const serverInfo = useServerInfo(); const providerInfo = useMemo(() => { var _a, _b; const namespaces = [ "org.keycloak.broker.social.SocialIdentityProvider", "org.keycloak.broker.provider.IdentityProvider", ]; for (const namespace of namespaces) { const social = (_b = (_a = serverInfo.componentTypes) === null || _a === void 0 ? void 0 : _a[namespace]) === null || _b === void 0 ? void 0 : _b.find(({ id }) => id === providerId); if (social) { return social; } } }, [serverInfo, providerId]); const { addAlert, addError } = useAlerts(); const navigate = useNavigate(); const { realm } = useRealm(); const [key, setKey] = useState(0); const refresh = () => setKey(key + 1); useFetch(() => adminClient.identityProviders.findOne({ alias }), (fetchedProvider) => { var _a, _b; if (!fetchedProvider) { throw new Error(t("notFound")); } reset(fetchedProvider); setProvider(fetchedProvider); if (fetchedProvider.config.authnContextClassRefs) { form.setValue("config.authnContextClassRefs", JSON.parse((_a = fetchedProvider.config) === null || _a === void 0 ? void 0 : _a.authnContextClassRefs)); } if (fetchedProvider.config.authnContextDeclRefs) { form.setValue("config.authnContextDeclRefs", JSON.parse((_b = fetchedProvider.config) === null || _b === void 0 ? void 0 : _b.authnContextDeclRefs)); } }, []); const toTab = (tab) => toIdentityProvider({ realm, alias, providerId, tab, }); const useTab = (tab) => useRoutableTab(toTab(tab)); const settingsTab = useTab("settings"); const mappersTab = useTab("mappers"); const permissionsTab = useTab("permissions"); const save = async (savedProvider) => { var _a, _b, _c, _d; const p = savedProvider || getValues(); const origAuthnContextClassRefs = (_a = p.config) === null || _a === void 0 ? void 0 : _a.authnContextClassRefs; if ((_b = p.config) === null || _b === void 0 ? void 0 : _b.authnContextClassRefs) p.config.authnContextClassRefs = JSON.stringify(p.config.authnContextClassRefs); const origAuthnContextDeclRefs = (_c = p.config) === null || _c === void 0 ? void 0 : _c.authnContextDeclRefs; if ((_d = p.config) === null || _d === void 0 ? void 0 : _d.authnContextDeclRefs) p.config.authnContextDeclRefs = JSON.stringify(p.config.authnContextDeclRefs); try { await adminClient.identityProviders.update({ alias }, { ...p, config: { ...provider === null || provider === void 0 ? void 0 : provider.config, ...p.config }, alias, providerId, }); if (origAuthnContextClassRefs) { p.config.authnContextClassRefs = origAuthnContextClassRefs; } if (origAuthnContextDeclRefs) { p.config.authnContextDeclRefs = origAuthnContextDeclRefs; } reset(p); addAlert(t("updateSuccessIdentityProvider"), AlertVariant.success); } catch (error) { addError("updateErrorIdentityProvider", error); } }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: "deleteProvider", messageKey: t("deleteConfirmIdentityProvider", { provider: alias }), continueButtonLabel: "delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { await adminClient.identityProviders.del({ alias: alias }); addAlert(t("deletedSuccessIdentityProvider"), AlertVariant.success); navigate(toIdentityProviders({ realm })); } catch (error) { addError("deleteErrorIdentityProvider", error); } }, }); const [toggleDeleteMapperDialog, DeleteMapperConfirm] = useConfirmDialog({ titleKey: "deleteProviderMapper", messageKey: t("deleteMapperConfirm", { mapper: selectedMapper === null || selectedMapper === void 0 ? void 0 : selectedMapper.name, }), continueButtonLabel: "delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { await adminClient.identityProviders.delMapper({ alias: alias, id: selectedMapper === null || selectedMapper === void 0 ? void 0 : selectedMapper.mapperId, }); addAlert(t("deleteMapperSuccess"), AlertVariant.success); refresh(); navigate(toIdentityProvider({ providerId, alias, tab: "mappers", realm })); } catch (error) { addError("deleteErrorIdentityProvider", error); } }, }); if (!provider) { return _jsx(KeycloakSpinner, {}); } const isOIDC = provider.providerId.includes("oidc"); const isSAML = provider.providerId.includes("saml"); const isSocial = !isOIDC && !isSAML; const loader = async () => { const [loaderMappers, loaderMapperTypes] = await Promise.all([ adminClient.identityProviders.findMappers({ alias }), adminClient.identityProviders.findMapperTypes({ alias }), ]); const components = loaderMappers.map((loaderMapper) => { const mapperType = Object.values(loaderMapperTypes).find((loaderMapperType) => loaderMapper.identityProviderMapper === loaderMapperType.id); const result = { ...mapperType, name: loaderMapper.name, type: mapperType === null || mapperType === void 0 ? void 0 : mapperType.name, mapperId: loaderMapper.id, }; return result; }); return components; }; const sections = [ { title: t("generalSettings"), panel: (_jsxs(FormAccess, { role: "manage-identity-providers", isHorizontal: true, onSubmit: handleSubmit(save), children: [isSocial && _jsx(GeneralSettings, { create: false, id: providerId }), isOIDC && _jsx(OIDCGeneralSettings, {}), isSAML && _jsx(SamlGeneralSettings, { isAliasReadonly: true }), providerInfo && (_jsx(DynamicComponents, { stringify: true, properties: providerInfo.properties }))] })), }, { title: t("oidcSettings"), isHidden: !isOIDC, panel: (_jsxs(_Fragment, { children: [_jsx(DiscoverySettings, { readOnly: false }), _jsxs(Form, { isHorizontal: true, className: "pf-v5-u-py-lg", children: [_jsx(Divider, {}), _jsx(OIDCAuthentication, { create: false })] }), _jsx(ExtendedNonDiscoverySettings, {})] })), }, { title: t("samlSettings"), isHidden: !isSAML, panel: _jsx(DescriptorSettings, { readOnly: false }), }, { title: t("reqAuthnConstraints"), isHidden: !isSAML, panel: (_jsx(FormAccess, { role: "manage-identity-providers", isHorizontal: true, onSubmit: handleSubmit(save), children: _jsx(ReqAuthnConstraints, {}) })), }, { title: t("advancedSettings"), panel: (_jsxs(FormAccess, { role: "manage-identity-providers", isHorizontal: true, onSubmit: handleSubmit(save), children: [_jsx(AdvancedSettings, { isOIDC: isOIDC, isSAML: isSAML }), _jsx(FixedButtonsGroup, { name: "idp-details", isSubmit: true, reset: reset })] })), }, ]; return (_jsxs(FormProvider, { ...form, children: [_jsx(DeleteConfirm, {}), _jsx(DeleteMapperConfirm, {}), _jsx(Controller, { name: "enabled", control: form.control, defaultValue: true, render: ({ field }) => (_jsx(Header, { value: field.value || false, onChange: field.onChange, save: save, toggleDeleteDialog: toggleDeleteDialog })) }), _jsx(PageSection, { variant: "light", className: "pf-v5-u-p-0", children: _jsxs(RoutableTabs, { isBox: true, defaultLocation: toTab("settings"), children: [_jsx(Tab, { id: "settings", title: _jsx(TabTitleText, { children: t("settings") }), ...settingsTab, children: _jsx(ScrollForm, { label: t("jumpToSection"), className: "pf-v5-u-px-lg", sections: sections }) }), _jsx(Tab, { id: "mappers", "data-testid": "mappers-tab", title: _jsx(TabTitleText, { children: t("mappers") }), ...mappersTab, children: _jsx(KeycloakDataTable, { emptyState: _jsx(ListEmptyState, { message: t("noMappers"), instructions: t("noMappersInstructions"), primaryActionText: t("addMapper"), onPrimaryAction: () => navigate(toIdentityProviderAddMapper({ realm, alias: alias, providerId: provider.providerId, tab: "mappers", })) }), loader: loader, ariaLabelKey: "mappersList", searchPlaceholderKey: "searchForMapper", toolbarItem: _jsx(ToolbarItem, { children: _jsx(Button, { id: "add-mapper-button", component: (props) => (_jsx(Link, { ...props, to: toIdentityProviderAddMapper({ realm, alias: alias, providerId: provider.providerId, tab: "mappers", }) })), "data-testid": "addMapper", children: t("addMapper") }) }), columns: [ { name: "name", displayKey: "name", cellRenderer: (row) => (_jsx(MapperLink, { ...row, provider: provider })), }, { name: "category", displayKey: "category", }, { name: "type", displayKey: "type", }, ], actions: [ { title: t("delete"), onRowClick: (mapper) => { setSelectedMapper(mapper); toggleDeleteMapperDialog(); }, }, ] }, key) }), isFeatureEnabled(Feature.AdminFineGrainedAuthz) && (_jsx(Tab, { id: "permissions", "data-testid": "permissionsTab", title: _jsx(TabTitleText, { children: t("permissions") }), ...permissionsTab, children: _jsx(PermissionsTab, { id: alias, type: "identityProviders" }) }))] }) })] })); } //# sourceMappingURL=DetailSettings.js.map