From 8c68b08c12ba371deda61662e3d048d63d07c56f Mon Sep 17 00:00:00 2001 From: Elias Schneider Date: Tue, 6 Jan 2026 13:49:10 +0100 Subject: [PATCH] fix: allow changing "require email address" if no SMTP credentials present --- frontend/messages/en.json | 4 +- .../lib/types/application-configuration.ts | 2 +- .../forms/app-config-email-form.svelte | 68 +++++++++++++++---- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index b31681f3..99e9198c 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -499,5 +499,7 @@ "save_and_sync": "Save and Sync", "scim_save_changes_description": "You have to save the changes before starting a SCIM sync. Do you want to save now?", "scopes": "Scopes", - "issuer_url": "Issuer URL" + "issuer_url": "Issuer URL", + "smtp_field_required_when_other_provided": "Required when any SMTP setting is provided", + "smtp_field_required_when_email_enabled": "Required when email notifications are enabled" } diff --git a/frontend/src/lib/types/application-configuration.ts b/frontend/src/lib/types/application-configuration.ts index 5ae1032f..54bbb0a1 100644 --- a/frontend/src/lib/types/application-configuration.ts +++ b/frontend/src/lib/types/application-configuration.ts @@ -21,7 +21,7 @@ export type AllAppConfig = AppConfig & { signupDefaultCustomClaims: CustomClaim[]; // Email smtpHost: string; - smtpPort: number; + smtpPort: string; smtpFrom: string; smtpUser: string; smtpPassword: string; diff --git a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte index 2da8c866..afd07fc0 100644 --- a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte +++ b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte @@ -31,20 +31,58 @@ let isSendingTestEmail = $state(false); - const formSchema = z.object({ - requireUserEmail: z.boolean(), - smtpHost: z.string().min(1), - smtpPort: z.number().min(1), - smtpUser: z.string(), - smtpPassword: z.string(), - smtpFrom: z.email(), - smtpTls: z.enum(['none', 'starttls', 'tls']), - smtpSkipCertVerify: z.boolean(), - emailOneTimeAccessAsUnauthenticatedEnabled: z.boolean(), - emailOneTimeAccessAsAdminEnabled: z.boolean(), - emailLoginNotificationEnabled: z.boolean(), - emailApiKeyExpirationEnabled: z.boolean() - }); + const formSchema = z + .object({ + requireUserEmail: z.boolean(), + smtpHost: z.string().optional(), + smtpPort: z + .preprocess((v: string) => (!v ? undefined : parseInt(v)), z.number().optional().nullable()) + .transform((v) => v?.toString() ?? '') + .optional(), + smtpUser: z.string().optional(), + smtpPassword: z.string().optional(), + smtpFrom: z.email().optional(), + smtpTls: z.enum(['none', 'starttls', 'tls']), + smtpSkipCertVerify: z.boolean(), + emailOneTimeAccessAsUnauthenticatedEnabled: z.boolean(), + emailOneTimeAccessAsAdminEnabled: z.boolean(), + emailLoginNotificationEnabled: z.boolean(), + emailApiKeyExpirationEnabled: z.boolean() + }) + .superRefine((data, ctx) => { + const requiredSmtpFields: (keyof z.infer)[] = [ + 'smtpHost', + 'smtpPort', + 'smtpFrom' + ]; + + const emailFields: (keyof z.infer)[] = [ + 'emailOneTimeAccessAsUnauthenticatedEnabled', + 'emailOneTimeAccessAsAdminEnabled', + 'emailLoginNotificationEnabled', + 'emailApiKeyExpirationEnabled' + ]; + + function requireFieldsWhen(condition: boolean, message: string) { + if (!condition) return; + + for (const f of requiredSmtpFields) { + if (!data[f]) { + ctx.addIssue({ + code: 'custom', + path: [f], + message + }); + } + } + } + + const anyProvided = requiredSmtpFields.some((f) => !!data[f]); + requireFieldsWhen(anyProvided, m.smtp_field_required_when_other_provided()); + + const emailEnabled = emailFields.some((f) => data[f]); + requireFieldsWhen(emailEnabled, m.smtp_field_required_when_email_enabled()); + }); let { inputs, ...form } = $derived(createForm(formSchema, appConfig)); @@ -106,7 +144,7 @@ bind:checked={$inputs.requireUserEmail.value} />

{m.smtp_configuration()}

-
+