fix(mail-webui): constrain focused profile updates

This commit is contained in:
2026-07-21 20:48:47 +02:00
parent 9f49591a98
commit 2e5921b3ff
3 changed files with 128 additions and 13 deletions

View File

@@ -42,6 +42,8 @@ import {
mailProfileEditTargetShowsProfileFields,
mailProfileEditTargetShowsSettingsPanel,
mailProfileEditTargetVisibleSections,
mailProfileCreateCredentialsPayload,
mailProfileTargetedUpdatePayload,
type MailProfileEditTarget,
type MailProfileProtocol
} from "./mailProfileEditorModel";
@@ -278,7 +280,7 @@ export function MailProfileScopeManager({
const created = await createMailServerProfile(settings, payload);
setSuccess(i18nMessage("i18n:govoplan-mail.profile_value_created.2a088d8d", { value0: created.name }));
} else {
const payload = updateProfilePayload(draft, editing);
const payload = updateProfilePayload(draft, editing, editingTarget);
const updated = await updateMailServerProfile(settings, editing.id, payload);
setSuccess(i18nMessage("i18n:govoplan-mail.profile_value_updated.fdbad0ea", { value0: updated.name }));
}
@@ -369,13 +371,16 @@ export function MailProfileScopeManager({
}
if (row.kind === "credential") {
return <TableActionGroup actions={[{
id: "edit-credentials", label: i18nMessage("i18n:govoplan-mail.edit_value_credentials.1e2dc4f6", { value0: row.protocol.toUpperCase() }), icon: <Pencil size={16} />, disabled: !canWriteProfiles || busy, onClick: () => openEdit(row.profile, { kind: "credentials", protocol: row.protocol })
id: "edit-credentials", label: i18nMessage("i18n:govoplan-mail.edit_value_credentials.1e2dc4f6", { value0: row.protocol.toUpperCase() }), icon: <Pencil size={16} />, disabled: !canWriteProfiles || !canManageCredentials || busy, onClick: () => openEdit(row.profile, { kind: "credentials", protocol: row.protocol })
}]} />;
}
const deactivationDeletesCredentials = Boolean(
row.profile.smtp_password_configured || row.profile.imap_password_configured
);
return <TableActionGroup actions={[
{ id: "edit", label: i18nMessage("i18n:govoplan-mail.edit_value.fad75899", { value0: row.profile.name }), icon: <Pencil size={16} />, disabled: !canWriteProfiles || busy, onClick: () => openEdit(row.profile) },
{ id: "deactivate", label: i18nMessage("i18n:govoplan-mail.deactivate_value.a276a667", { value0: row.profile.name }), icon: <Trash2 size={16} />, variant: "danger", applicable: row.profile.is_active, disabled: !canWriteProfiles || busy, onClick: () => setDeactivating(row.profile) }
{ id: "deactivate", label: i18nMessage("i18n:govoplan-mail.deactivate_value.a276a667", { value0: row.profile.name }), icon: <Trash2 size={16} />, variant: "danger", applicable: row.profile.is_active, disabled: !canWriteProfiles || busy || (deactivationDeletesCredentials && !canManageCredentials), onClick: () => setDeactivating(row.profile) }
]} />;
}
@@ -1092,6 +1097,7 @@ function profileToDraft(profile: MailServerProfile): ProfileDraft {
}
function createProfilePayload(draft: ProfileDraft, scopeType: MailProfileScope, scopeId: string | null): MailServerProfilePayload {
const credentials = profileCreateCredentialsPayload(draft);
return {
name: draft.name.trim(),
slug: mailTextOrNull(draft.slug),
@@ -1101,21 +1107,27 @@ function createProfilePayload(draft: ProfileDraft, scopeType: MailProfileScope,
scope_id: scopeId,
smtp: smtpServerPayload(draft),
imap: hasDraftImapSettings(draft) ? imapServerPayload(draft) : null,
credentials: profileCredentialsPayload(draft, false)
...(credentials ? { credentials } : {})
};
}
function updateProfilePayload(draft: ProfileDraft, profile: MailServerProfile): MailServerProfileUpdatePayload {
return {
name: draft.name.trim(),
slug: mailTextOrNull(draft.slug),
description: draft.description.trim(),
is_active: draft.isActive,
function updateProfilePayload(
draft: ProfileDraft,
profile: MailServerProfile,
target: MailProfileEditTarget
): MailServerProfileUpdatePayload {
return mailProfileTargetedUpdatePayload(target, {
profile: {
name: draft.name.trim(),
slug: mailTextOrNull(draft.slug),
description: draft.description.trim(),
is_active: draft.isActive
},
smtp: smtpServerPayload(draft),
imap: hasDraftImapSettings(draft) ? imapServerPayload(draft) : null,
credentials: profileCredentialsPayload(draft, true),
clear_imap: !hasDraftImapSettings(draft) && Boolean(profile.imap)
};
clearImap: !hasDraftImapSettings(draft) && Boolean(profile.imap)
}) as MailServerProfileUpdatePayload;
}
function smtpServerPayload(draft: ProfileDraft): MailSmtpTestPayload {
@@ -1139,6 +1151,13 @@ function profileCredentialsPayload(draft: ProfileDraft, preserveBlankPassword: b
};
}
function profileCreateCredentialsPayload(draft: ProfileDraft) {
return mailProfileCreateCredentialsPayload(
mailTransportCredentialsPayload(draft.smtpUsername, draft.smtpPassword, true),
mailTransportCredentialsPayload(draft.imapUsername, draft.imapPassword, true)
);
}
function rawSmtpPayload(draft: ProfileDraft, preserveBlankPassword: boolean): MailSmtpTestPayload {
return { ...smtpServerPayload(draft), ...mailTransportCredentialsPayload(draft.smtpUsername, draft.smtpPassword, preserveBlankPassword) };
}