fix(mail-webui): constrain focused profile updates
This commit is contained in:
@@ -23,6 +23,22 @@ export type MailProfileChildDescriptor = {
|
||||
protocol: MailProfileProtocol;
|
||||
};
|
||||
|
||||
export type MailProfileTransportCredentialsLike = {
|
||||
username?: string | null;
|
||||
password?: string | null;
|
||||
};
|
||||
|
||||
export type MailProfileTargetedUpdateParts = {
|
||||
profile: Record<string, unknown>;
|
||||
smtp: Record<string, unknown>;
|
||||
imap: Record<string, unknown> | null;
|
||||
credentials: {
|
||||
smtp: MailProfileTransportCredentialsLike;
|
||||
imap: MailProfileTransportCredentialsLike;
|
||||
};
|
||||
clearImap: boolean;
|
||||
};
|
||||
|
||||
export function mailProfileChildDescriptors(profile: MailProfileTreeProfileLike): MailProfileChildDescriptor[] {
|
||||
const children: MailProfileChildDescriptor[] = [
|
||||
{ kind: "server", id: `server:${profile.id}:smtp`, protocol: "smtp" },
|
||||
@@ -58,3 +74,42 @@ export function mailProfileEditTargetShowsProfileFields(target: MailProfileEditT
|
||||
export function mailProfileEditTargetShowsSettingsPanel(target: MailProfileEditTarget): boolean {
|
||||
return target.kind !== "profile";
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the PATCH authority surface equal to the focused editor. Profile and
|
||||
* server edits must not accidentally replay credential fields merely because
|
||||
* the form draft contains their displayed values.
|
||||
*/
|
||||
export function mailProfileTargetedUpdatePayload(
|
||||
target: MailProfileEditTarget,
|
||||
parts: MailProfileTargetedUpdateParts
|
||||
): Record<string, unknown> {
|
||||
if (target.kind === "profile") return parts.profile;
|
||||
if (target.kind === "server") {
|
||||
if (target.protocol === "smtp") return { smtp: parts.smtp };
|
||||
return parts.imap === null
|
||||
? { imap: null, clear_imap: parts.clearImap }
|
||||
: { imap: parts.imap };
|
||||
}
|
||||
if (target.kind === "credentials") {
|
||||
return { credentials: { [target.protocol]: parts.credentials[target.protocol] } };
|
||||
}
|
||||
throw new Error("Create is not an update target");
|
||||
}
|
||||
|
||||
/** Omit blank create credentials so profile-write remains independent. */
|
||||
export function mailProfileCreateCredentialsPayload(
|
||||
smtp: MailProfileTransportCredentialsLike,
|
||||
imap: MailProfileTransportCredentialsLike
|
||||
): {smtp?: MailProfileTransportCredentialsLike;imap?: MailProfileTransportCredentialsLike;} | undefined {
|
||||
const populated = (value: MailProfileTransportCredentialsLike): MailProfileTransportCredentialsLike =>
|
||||
Object.fromEntries(
|
||||
Object.entries(value).filter(([, item]) => item !== null && item !== undefined && item !== "")
|
||||
);
|
||||
const smtpCredentials = populated(smtp);
|
||||
const imapCredentials = populated(imap);
|
||||
const result: {smtp?: MailProfileTransportCredentialsLike;imap?: MailProfileTransportCredentialsLike;} = {};
|
||||
if (Object.keys(smtpCredentials).length > 0) result.smtp = smtpCredentials;
|
||||
if (Object.keys(imapCredentials).length > 0) result.imap = imapCredentials;
|
||||
return Object.keys(result).length > 0 ? result : undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user