import { useState } from "react"; import { ActionGroup, AlertVariant, Button, Form, PageSection, } from "@patternfly/react-core"; import { FormProvider, useForm, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom-v5-compat"; import { ScrollForm } from "../components/scroll-form/ScrollForm"; import type UserProfileConfig from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig"; import { AttributeGeneralSettings } from "./user-profile/attribute/AttributeGeneralSettings"; import { AttributePermission } from "./user-profile/attribute/AttributePermission"; import { AttributeValidations } from "./user-profile/attribute/AttributeValidations"; import { toUserProfile } from "./routes/UserProfile"; import { ViewHeader } from "../components/view-header/ViewHeader"; import { AttributeAnnotations } from "./user-profile/attribute/AttributeAnnotations"; import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { useAlerts } from "../components/alert/Alerts"; import { UserProfileProvider } from "./user-profile/UserProfileContext"; import type { UserProfileAttribute } from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig"; import type { AttributeParams } from "./routes/Attribute"; import type { KeyValueType } from "../components/key-value-form/key-value-convert"; import { convertToFormValues } from "../util"; import { flatten } from "flat"; import "./realm-settings-section.css"; type UserProfileAttributeType = UserProfileAttribute & Attribute & Permission; type Attribute = { roles: string[]; scopes: string[]; isRequired: boolean; }; type Permission = { view: PermissionView[]; edit: PermissionEdit[]; }; type PermissionView = [ { adminView: boolean; userView: boolean; } ]; type PermissionEdit = [ { adminEdit: boolean; userEdit: boolean; } ]; const CreateAttributeFormContent = ({ save, }: { save: (profileConfig: UserProfileConfig) => void; }) => { const { t } = useTranslation("realm-settings"); const form = useFormContext(); const { realm, attributeName } = useParams(); const editMode = attributeName ? true : false; return ( }, { title: t("permission"), panel: }, { title: t("validations"), panel: }, { title: t("annotations"), panel: }, ]} />
{t("common:cancel")}
); }; export default function NewAttributeSettings() { const { realm, attributeName } = useParams(); const { adminClient } = useAdminClient(); const form = useForm({ shouldUnregister: false }); const { t } = useTranslation("realm-settings"); const navigate = useNavigate(); const { addAlert, addError } = useAlerts(); const [config, setConfig] = useState(null); const editMode = attributeName ? true : false; const convert = (obj: Record[] | undefined) => Object.entries(obj || []).map(([key, value]) => ({ key, value, })); useFetch( () => adminClient.users.getProfile(), (config) => { setConfig(config); const { annotations, validations, permissions, selector, required, ...values } = config.attributes!.find( (attribute) => attribute.name === attributeName ) || {}; convertToFormValues(values, form.setValue); Object.entries( flatten({ permissions, selector, required }, { safe: true }) ).map(([key, value]) => form.setValue(key, value)); form.setValue("annotations", convert(annotations)); form.setValue("validations", convert(validations)); form.setValue("isRequired", required !== undefined); }, [] ); const save = async (profileConfig: UserProfileAttributeType) => { const validations = profileConfig.validations?.reduce( (prevValidations: any, currentValidations: any) => { prevValidations[currentValidations.key] = currentValidations.value?.length === 0 ? {} : currentValidations.value; return prevValidations; }, {} ); const annotations = (profileConfig.annotations! as KeyValueType[]).reduce( (obj, item) => Object.assign(obj, { [item.key]: item.value }), {} ); const patchAttributes = () => config?.attributes!.map((attribute) => { if (attribute.name !== attributeName) { return attribute; } delete attribute.required; return Object.assign( { ...attribute, name: attributeName, displayName: profileConfig.displayName!, validations, selector: profileConfig.selector, permissions: profileConfig.permissions!, annotations, }, profileConfig.isRequired ? { required: profileConfig.required } : undefined, profileConfig.group ? { group: profileConfig.group } : undefined ); }); const addAttribute = () => config?.attributes!.concat([ Object.assign( { name: profileConfig.name, displayName: profileConfig.displayName!, required: profileConfig.isRequired ? profileConfig.required : {}, validations, selector: profileConfig.selector, permissions: profileConfig.permissions!, annotations, }, profileConfig.isRequired ? { required: profileConfig.required } : undefined, profileConfig.group ? { group: profileConfig.group } : undefined ), ] as UserProfileAttribute); const updatedAttributes = editMode ? patchAttributes() : addAttribute(); try { await adminClient.users.updateProfile({ ...config, attributes: updatedAttributes as UserProfileAttribute[], realm, }); navigate(toUserProfile({ realm, tab: "attributes" })); addAlert( t("realm-settings:createAttributeSuccess"), AlertVariant.success ); } catch (error) { addError("realm-settings:createAttributeError", error); } }; return ( form.handleSubmit(save)()} /> ); }