@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
222 lines • 13.2 kB
JavaScript
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