Allow editing non-SCIM fields on SCIM-managed profiles

Contract start and end dates are never synced by SCIM, so they
should remain editable even when a profile is SCIM-managed.
The backend now skips overwriting SCIM-synced fields (fullName,
kind, position, additionalEmailAddresses) for SCIM profiles,
and the frontend disables only those fields instead of the
entire form.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-03-24 10:38:12 +01:00
parent 359f85f5da
commit 784c88895a
2 changed files with 14 additions and 9 deletions

View File

@@ -77,6 +77,7 @@ export function PersonForm(props: {
id?: string; id?: string;
connectionId?: DataID; connectionId?: DataID;
disabled?: boolean; disabled?: boolean;
scimManaged?: boolean;
defaultValues?: z.infer<typeof schema>; defaultValues?: z.infer<typeof schema>;
onSubmit?: () => void; onSubmit?: () => void;
}) { }) {
@@ -84,6 +85,7 @@ export function PersonForm(props: {
id, id,
connectionId = "", connectionId = "",
disabled = false, disabled = false,
scimManaged = false,
defaultValues = { defaultValues = {
fullName: "", fullName: "",
emailAddress: "", emailAddress: "",
@@ -162,7 +164,7 @@ export function PersonForm(props: {
return ( return (
<form onSubmit={e => void handleSubmit(e)} className="space-y-4"> <form onSubmit={e => void handleSubmit(e)} className="space-y-4">
<Field label={__("Full name *")} {...register("fullName")} type="text" disabled={disabled} /> <Field label={__("Full name *")} {...register("fullName")} type="text" disabled={disabled || scimManaged} />
{id {id
? ( ? (
<> <>
@@ -223,7 +225,7 @@ export function PersonForm(props: {
name="kind" name="kind"
type="select" type="select"
label={__("Type")} label={__("Type")}
disabled={disabled} disabled={disabled || scimManaged}
> >
{getRoles(__).map(role => ( {getRoles(__).map(role => (
<Option key={role.value} value={role.value}> <Option key={role.value} value={role.value}>
@@ -236,9 +238,9 @@ export function PersonForm(props: {
{...register("position")} {...register("position")}
type="text" type="text"
placeholder={__("e.g. CEO, CFO, etc.")} placeholder={__("e.g. CEO, CFO, etc.")}
disabled={disabled} disabled={disabled || scimManaged}
/> />
<EmailsField control={control} register={register} disabled={disabled} /> <EmailsField control={control} register={register} disabled={disabled || scimManaged} />
<Field label={__("Contract start date")}> <Field label={__("Contract start date")}>
<Input <Input
{...register("contractStartDate")} {...register("contractStartDate")}
@@ -272,7 +274,8 @@ export function PersonFormLoader(props: { fragmentRef: PersonFormFragment$key })
return ( return (
<PersonForm <PersonForm
id={person.id} id={person.id}
disabled={!person.canUpdate || person.source === "SCIM"} disabled={!person.canUpdate}
scimManaged={person.source === "SCIM"}
defaultValues={ defaultValues={
{ {
kind: person.kind, kind: person.kind,

View File

@@ -977,10 +977,12 @@ func (s *OrganizationService) UpdateUser(ctx context.Context, req *UpdateUserReq
return fmt.Errorf("cannot load profile: %w", err) return fmt.Errorf("cannot load profile: %w", err)
} }
profile.FullName = req.FullName if profile.Source != coredata.ProfileSourceSCIM {
profile.Kind = req.Kind profile.FullName = req.FullName
profile.AdditionalEmailAddresses = req.AdditionalEmailAddresses profile.Kind = req.Kind
profile.Position = req.Position profile.AdditionalEmailAddresses = req.AdditionalEmailAddresses
profile.Position = req.Position
}
if req.ContractStartDate != nil { if req.ContractStartDate != nil {
profile.ContractStartDate = *req.ContractStartDate profile.ContractStartDate = *req.ContractStartDate