UNPKG

@keycloakify/keycloak-admin-ui

Version:
222 lines 13.2 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { isUserProfileError, setUserProfileServerError, useAlerts, useFetch, } from "../ui-shared"; import { AlertVariant, ButtonVariant, DropdownItem, Label, PageSection, Tab, TabTitleText, Tooltip, } from "@patternfly/react-core"; import { InfoCircleIcon } from "@patternfly/react-icons"; import { useState } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { useAdminClient } from "../admin-client"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { KeycloakSpinner } from "../ui-shared"; import { RoutableTabs, useRoutableTab, } from "../components/routable-tabs/RoutableTabs"; import { ViewHeader } from "../components/view-header/ViewHeader"; import { useAccess } from "../context/access/Access"; import { useRealm } from "../context/realm-context/RealmContext"; import { UserProfileProvider } from "../realm-settings/user-profile/UserProfileContext"; import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled"; import { useParams } from "../utils/useParams"; import { Organizations } from "../user/Organizations"; import { UserAttributes } from "../user/UserAttributes"; import { UserConsents } from "../user/UserConsents"; import { UserCredentials } from "../user/UserCredentials"; import { UserForm } from "../user/UserForm"; import { UserGroups } from "../user/UserGroups"; import { UserIdentityProviderLinks } from "../user/UserIdentityProviderLinks"; import { UserRoleMapping } from "../user/UserRoleMapping"; import { UserSessions } from "../user/UserSessions"; import { filterManagedAttributes, toUserFormFields, toUserRepresentation, } from "../user/form-state"; import { toUser } from "../user/routes/User"; import { toUsers } from "../user/routes/Users"; import { isLightweightUser } from "../user/utils"; import "./user-section.css"; export default function EditUser() { var _a, _b, _c, _d; const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { addAlert, addError } = useAlerts(); const navigate = useNavigate(); const { hasAccess } = useAccess(); const { id } = useParams(); const { realm: realmName, realmRepresentation: realm } = useRealm(); // Validation of form fields is performed on server, thus we need to clear all errors before submit const clearAllErrorsBeforeSubmit = async (values) => ({ values, errors: {}, }); const form = useForm({ mode: "onChange", resolver: clearAllErrorsBeforeSubmit, }); const [user, setUser] = useState(); const [bruteForced, setBruteForced] = useState(); const [isUnmanagedAttributesEnabled, setUnmanagedAttributesEnabled] = useState(); const [userProfileMetadata, setUserProfileMetadata] = useState(); const [refreshCount, setRefreshCount] = useState(0); const refresh = () => setRefreshCount((count) => count + 1); const lightweightUser = isLightweightUser(user === null || user === void 0 ? void 0 : user.id); const [upConfig, setUpConfig] = useState(); const [realmHasOrganizations, setRealmHasOrganizations] = useState(false); const isFeatureEnabled = useIsFeatureEnabled(); const showOrganizations = isFeatureEnabled(Feature.Organizations) && (realm === null || realm === void 0 ? void 0 : realm.organizationsEnabled); const toTab = (tab) => toUser({ realm: realmName, id: (user === null || user === void 0 ? void 0 : user.id) || "", tab, }); const useTab = (tab) => useRoutableTab(toTab(tab)); const settingsTab = useTab("settings"); const attributesTab = useTab("attributes"); const credentialsTab = useTab("credentials"); const roleMappingTab = useTab("role-mapping"); const groupsTab = useTab("groups"); const organizationsTab = useTab("organizations"); const consentsTab = useTab("consents"); const identityProviderLinksTab = useTab("identity-provider-links"); const sessionsTab = useTab("sessions"); useFetch(async () => Promise.all([ adminClient.users.findOne({ id: id, userProfileMetadata: true, }), adminClient.attackDetection.findOne({ id: id }), adminClient.users.getUnmanagedAttributes({ id: id }), adminClient.users.getProfile({ realm: realmName }), showOrganizations ? adminClient.organizations.find({ first: 0, max: 1 }) : [], ]), ([userData, attackDetection, unmanagedAttributes, upConfig, organizations,]) => { if (!userData || !realm || !attackDetection) { throw new Error(t("notFound")); } const { userProfileMetadata, ...user } = userData; setUserProfileMetadata(userProfileMetadata); user.unmanagedAttributes = unmanagedAttributes; user.attributes = filterManagedAttributes(user.attributes, unmanagedAttributes); if (upConfig.unmanagedAttributePolicy !== undefined) { setUnmanagedAttributesEnabled(true); } setUser(user); setUpConfig(upConfig); const isBruteForceProtected = realm.bruteForceProtected; const isLocked = isBruteForceProtected && attackDetection.disabled; setBruteForced({ isBruteForceProtected, isLocked }); setRealmHasOrganizations(organizations.length === 1); form.reset(toUserFormFields(user)); }, [refreshCount]); const save = async (data) => { try { await adminClient.users.update({ id: user.id }, toUserRepresentation(data)); addAlert(t("userSaved"), AlertVariant.success); refresh(); } catch (error) { if (isUserProfileError(error)) { if (isUnmanagedAttributesEnabled && Array.isArray(data.unmanagedAttributes)) { const unmanagedAttributeErrors = new Array(data.unmanagedAttributes.length); let someUnmanagedAttributeError = false; setUserProfileServerError(error, (field, params) => { if (field.startsWith("attributes.")) { const attributeName = field.substring("attributes.".length); data.unmanagedAttributes.forEach((attr, index) => { if (attr.key === attributeName) { unmanagedAttributeErrors[index] = params; someUnmanagedAttributeError = true; } }); } else { form.setError(field, params); } }, ((key, param) => t(key, param))); if (someUnmanagedAttributeError) { form.setError("unmanagedAttributes", unmanagedAttributeErrors); } } else { setUserProfileServerError(error, form.setError, ((key, param) => t(key, param))); } addError("userNotSaved", ""); } else { addError("userCreateError", error); } } }; const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({ titleKey: "disableConfirmUserTitle", messageKey: "disableConfirmUser", continueButtonLabel: "disable", onConfirm: () => { save({ ...toUserFormFields(user), enabled: false, }); }, }); const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: "deleteConfirm", messageKey: "deleteConfirmCurrentUser", continueButtonLabel: "delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { if (lightweightUser) { await adminClient.users.logout({ id: user.id }); } else { await adminClient.users.del({ id: user.id }); } addAlert(t("userDeletedSuccess"), AlertVariant.success); navigate(toUsers({ realm: realmName })); } catch (error) { addError("userDeletedError", error); } }, }); const [toggleImpersonateDialog, ImpersonateConfirm] = useConfirmDialog({ titleKey: "impersonateConfirm", messageKey: "impersonateConfirmDialog", continueButtonLabel: "impersonate", onConfirm: async () => { try { const data = await adminClient.users.impersonation({ id: user.id }, { user: user.id, realm: realmName }); if (data.sameRealm) { window.location = data.redirect; } else { window.open(data.redirect, "_blank"); } } catch (error) { addError("impersonateError", error); } }, }); if (!user || !bruteForced) { return _jsx(KeycloakSpinner, {}); } return (_jsxs(_Fragment, { children: [_jsx(ImpersonateConfirm, {}), _jsx(DeleteConfirm, {}), _jsx(DisableConfirm, {}), _jsx(ViewHeader, { titleKey: user.username, className: "kc-username-view-header", divider: false, badges: lightweightUser ? [ { text: (_jsx(Tooltip, { content: t("transientUserTooltip"), children: _jsx(Label, { "data-testid": "user-details-label-transient-user", icon: _jsx(InfoCircleIcon, {}), children: t("transientUser") }) })), }, ] : [], dropdownItems: [ _jsx(DropdownItem, { isDisabled: !((_a = user.access) === null || _a === void 0 ? void 0 : _a.impersonate), onClick: () => toggleImpersonateDialog(), children: t("impersonate") }, "impersonate"), _jsx(DropdownItem, { isDisabled: !((_b = user.access) === null || _b === void 0 ? void 0 : _b.manage), onClick: () => toggleDeleteDialog(), children: t("delete") }, "delete"), ], onToggle: (value) => { if (!value) { toggleDisableDialog(); } else { save({ ...toUserFormFields(user), enabled: value, }); } }, isEnabled: user.enabled }), _jsx(PageSection, { variant: "light", className: "pf-v5-u-p-0", children: _jsx(UserProfileProvider, { children: _jsx(FormProvider, { ...form, children: _jsxs(RoutableTabs, { isBox: true, mountOnEnter: true, defaultLocation: toTab("settings"), children: [_jsx(Tab, { "data-testid": "user-details-tab", title: _jsx(TabTitleText, { children: t("details") }), ...settingsTab, children: _jsx(PageSection, { variant: "light", children: _jsx(UserForm, { form: form, realm: realm, user: user, bruteForce: bruteForced, userProfileMetadata: userProfileMetadata, refresh: refresh, save: save }) }) }), isUnmanagedAttributesEnabled && (_jsx(Tab, { "data-testid": "attributes", title: _jsx(TabTitleText, { children: t("attributes") }), ...attributesTab, children: _jsx(UserAttributes, { user: user, save: save, upConfig: upConfig }) })), _jsx(Tab, { "data-testid": "credentials", isHidden: !((_c = user.access) === null || _c === void 0 ? void 0 : _c.view), title: _jsx(TabTitleText, { children: t("credentials") }), ...credentialsTab, children: _jsx(UserCredentials, { user: user, setUser: setUser }) }), _jsx(Tab, { "data-testid": "role-mapping-tab", isHidden: !((_d = user.access) === null || _d === void 0 ? void 0 : _d.view), title: _jsx(TabTitleText, { children: t("roleMapping") }), ...roleMappingTab, children: _jsx(UserRoleMapping, { id: user.id, name: user.username }) }), hasAccess("query-groups") && (_jsx(Tab, { "data-testid": "user-groups-tab", title: _jsx(TabTitleText, { children: t("groups") }), ...groupsTab, children: _jsx(UserGroups, { user: user }) })), showOrganizations && realmHasOrganizations && (_jsx(Tab, { "data-testid": "user-organizations-tab", title: _jsx(TabTitleText, { children: t("organizations") }), ...organizationsTab, children: _jsx(Organizations, {}) })), _jsx(Tab, { "data-testid": "user-consents-tab", title: _jsx(TabTitleText, { children: t("consents") }), ...consentsTab, children: _jsx(UserConsents, {}) }), _jsx(Tab, { "data-testid": "identity-provider-links-tab", title: _jsx(TabTitleText, { children: t("identityProviderLinks") }), ...identityProviderLinksTab, children: _jsx(UserIdentityProviderLinks, { userId: user.id }) }), _jsx(Tab, { "data-testid": "user-sessions-tab", title: _jsx(TabTitleText, { children: t("sessions") }), ...sessionsTab, children: _jsx(UserSessions, {}) })] }) }) }) })] })); } //# sourceMappingURL=EditUser.js.map