mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-30 04:29:05 +01:00
feat: add ability to force email verification (#1837)
This commit is contained in:
+68
-9
@@ -46,6 +46,18 @@
|
||||
}
|
||||
});
|
||||
|
||||
const emailVerificationOptions = $derived({
|
||||
disabled: { label: m.disabled(), description: m.email_verification_disabled_description() },
|
||||
optional: {
|
||||
label: m.email_verification_optional(),
|
||||
description: m.email_verification_optional_description()
|
||||
},
|
||||
required: {
|
||||
label: m.email_verification_required(),
|
||||
description: m.email_verification_required_description()
|
||||
}
|
||||
});
|
||||
|
||||
let isSendingTestEmail = $state(false);
|
||||
|
||||
const formSchema = z
|
||||
@@ -63,7 +75,7 @@
|
||||
smtpTls: z.enum(['none', 'starttls', 'tls']),
|
||||
smtpSkipCertVerify: z.boolean(),
|
||||
emailOneTimeAccessAsUnauthenticatedEnabled: z.boolean(),
|
||||
emailVerificationEnabled: z.boolean(),
|
||||
emailVerification: z.enum(['disabled', 'optional', 'required']),
|
||||
emailOneTimeAccessAsAdminEnabled: z.boolean(),
|
||||
emailLoginNotificationMode: z.enum([
|
||||
'disabled',
|
||||
@@ -82,7 +94,6 @@
|
||||
|
||||
const emailFields: (keyof z.infer<typeof formSchema>)[] = [
|
||||
'emailOneTimeAccessAsUnauthenticatedEnabled',
|
||||
'emailVerificationEnabled',
|
||||
'emailOneTimeAccessAsAdminEnabled',
|
||||
'emailApiKeyExpirationEnabled'
|
||||
];
|
||||
@@ -105,8 +116,19 @@
|
||||
requireFieldsWhen(anyProvided, m.smtp_field_required_when_other_provided());
|
||||
|
||||
const emailEnabled =
|
||||
data.emailLoginNotificationMode !== 'disabled' || emailFields.some((f) => data[f]);
|
||||
data.emailLoginNotificationMode !== 'disabled' ||
|
||||
data.emailVerification !== 'disabled' ||
|
||||
emailFields.some((f) => data[f]);
|
||||
requireFieldsWhen(emailEnabled, m.smtp_field_required_when_email_enabled());
|
||||
|
||||
// Requiring verification only protects accounts that have an email
|
||||
if (data.emailVerification === 'required' && !data.requireUserEmail) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
path: ['emailVerification'],
|
||||
message: m.email_verification_required_needs_user_email()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const formStore = createForm(formSchema, pickSchemaValues(formSchema, appConfig));
|
||||
@@ -175,10 +197,53 @@
|
||||
description={m.require_user_email_description()}
|
||||
bind:checked={$inputs.requireUserEmail.value}
|
||||
/>
|
||||
<Field.Field>
|
||||
<div>
|
||||
<Field.Label for="email-verification">{m.email_verification()}</Field.Label>
|
||||
<Field.Description>{m.email_verification_description()}</Field.Description>
|
||||
</div>
|
||||
<Select.Root
|
||||
type="single"
|
||||
disabled={$appConfigStore.uiConfigDisabled}
|
||||
value={$inputs.emailVerification.value}
|
||||
allowDeselect={false}
|
||||
onValueChange={(value) => {
|
||||
$inputs.emailVerification.value = value as AllAppConfig['emailVerification'];
|
||||
// Emails verified by default would let every new account skip the verification
|
||||
if (value === 'required') {
|
||||
$inputs.emailsVerified.value = false;
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Select.Trigger
|
||||
id="email-verification"
|
||||
class="w-full"
|
||||
aria-invalid={!!$inputs.emailVerification.error}
|
||||
>
|
||||
{emailVerificationOptions[$inputs.emailVerification.value].label}
|
||||
</Select.Trigger>
|
||||
<Select.Content class="w-[calc(var(--bits-select-anchor-width)+--spacing(3))]">
|
||||
<Select.Group>
|
||||
{#each Object.entries(emailVerificationOptions) as [value, option] (value)}
|
||||
<Select.Item {value} label={option.label}>
|
||||
<div class="flex flex-col items-start gap-1 whitespace-normal">
|
||||
<span class="font-medium">{option.label}</span>
|
||||
<span class="text-muted-foreground text-xs">{option.description}</span>
|
||||
</div>
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Group>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
{#if $inputs.emailVerification.error}
|
||||
<Field.Error>{$inputs.emailVerification.error}</Field.Error>
|
||||
{/if}
|
||||
</Field.Field>
|
||||
<SwitchWithLabel
|
||||
id="emails-verified-by-default"
|
||||
label={m.emails_verified_by_default()}
|
||||
description={m.emails_verified_by_default_description()}
|
||||
disabled={$inputs.emailVerification.value === 'required'}
|
||||
bind:checked={$inputs.emailsVerified.value}
|
||||
/>
|
||||
</div>
|
||||
@@ -246,12 +311,6 @@
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</Field.Field>
|
||||
<SwitchWithLabel
|
||||
id="email-verification"
|
||||
label={m.email_verification()}
|
||||
description={m.email_verification_description()}
|
||||
bind:checked={$inputs.emailVerificationEnabled.value}
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
id="email-login-admin"
|
||||
label={m.email_login_code_from_admin()}
|
||||
|
||||
Reference in New Issue
Block a user