feat: add email regex validation for user registration (#835)

This commit is contained in:
Dream Hunter
2026-02-16 12:40:20 +08:00
committed by GitHub
parent 56351ed963
commit bde08b9d55
6 changed files with 47 additions and 1 deletions

View File

@@ -21,6 +21,8 @@ const { t } = useI18n({
manualInputPrompt: 'Type and press Enter to add',
mailAllowList: 'Mail Address Allow List',
maxAddressCount: 'Maximum number of email addresses that can be binded',
emailCheckRegex: 'Email Check Regex (e.g. ^[^.]+@.+$ to disallow dots before @)',
enableEmailCheckRegex: 'Enable Email Check Regex',
},
zh: {
save: '保存',
@@ -33,6 +35,8 @@ const { t } = useI18n({
manualInputPrompt: '输入后按回车键添加',
mailAllowList: '邮件地址白名单',
maxAddressCount: '可绑定最大邮箱地址数量',
emailCheckRegex: '邮箱正则校验 (例如 ^[^.]+@.+$ 禁止@前面有.)',
enableEmailCheckRegex: '启用邮箱正则校验',
}
}
});
@@ -53,6 +57,8 @@ const userSettings = ref({
enableMailAllowList: false,
mailAllowList: commonMail,
maxAddressCount: 5,
enableEmailCheckRegex: false,
emailCheckRegex: "",
});
const fetchData = async () => {
@@ -125,6 +131,16 @@ onMounted(async () => {
:placeholder="t('maxAddressCount')" />
</n-input-group>
</n-form-item-row>
<n-form-item-row :label="t('enableEmailCheckRegex')">
<n-input-group>
<n-checkbox v-model:checked="userSettings.enableEmailCheckRegex" style="width: 20%;">
{{ t('enable') }}
</n-checkbox>
<n-input v-model:value="userSettings.emailCheckRegex"
v-if="userSettings.enableEmailCheckRegex"
style="width: 80%;" :placeholder="t('emailCheckRegex')" />
</n-input-group>
</n-form-item-row>
</n-form>
</n-card>
</div>

View File

@@ -26,6 +26,7 @@ const messages: LocaleMessages = {
FailedToRegisterMsg: "Failed to register",
UserRegistrationDisabledMsg: "User registration is disabled, please contact the administrator",
UserMailDomainMustInMsg: "User mail domain must be in this list",
UserEmailNotMatchRegexMsg: "Email address format does not match the required pattern",
InvalidVerifyCodeMsg: "Invalid verify code",
InvalidEmailOrPasswordMsg: "Invalid email or password",
VerifyMailSenderNotSetMsg: "Verify mail sender address is not set, please contact the administrator",

View File

@@ -24,6 +24,7 @@ export type LocaleMessages = {
FailedToRegisterMsg: string
UserRegistrationDisabledMsg: string
UserMailDomainMustInMsg: string
UserEmailNotMatchRegexMsg: string
InvalidVerifyCodeMsg: string
InvalidEmailOrPasswordMsg: string
VerifyMailSenderNotSetMsg: string

View File

@@ -26,6 +26,7 @@ const messages: LocaleMessages = {
FailedToRegisterMsg: "注册失败",
UserRegistrationDisabledMsg: "用户注册已禁用, 请联系管理员",
UserMailDomainMustInMsg: "用户邮箱域必须在此列表中",
UserEmailNotMatchRegexMsg: "邮箱地址格式不符合要求",
InvalidVerifyCodeMsg: "无效的验证码",
InvalidEmailOrPasswordMsg: "无效的邮箱或密码",
VerifyMailSenderNotSetMsg: "验证邮件发送邮箱未设置, 请联系管理员",

View File

@@ -99,11 +99,14 @@ export class UserSettings {
enableMailAllowList: boolean | undefined;
mailAllowList: string[] | undefined;
maxAddressCount: number;
enableEmailCheckRegex: boolean | undefined;
emailCheckRegex: string | undefined;
constructor(data: UserSettings | undefined | null) {
const {
enable, enableMailVerify, verifyMailSender,
enableMailAllowList, mailAllowList, maxAddressCount
enableMailAllowList, mailAllowList, maxAddressCount,
enableEmailCheckRegex, emailCheckRegex
} = data || {};
this.enable = enable;
this.enableMailVerify = enableMailVerify;
@@ -111,6 +114,8 @@ export class UserSettings {
this.enableMailAllowList = enableMailAllowList;
this.mailAllowList = mailAllowList;
this.maxAddressCount = maxAddressCount || 5;
this.enableEmailCheckRegex = enableEmailCheckRegex;
this.emailCheckRegex = emailCheckRegex;
}
}

View File

@@ -27,6 +27,17 @@ export default {
) {
return c.text(`${msgs.UserMailDomainMustInMsg} ${JSON.stringify(settings.mailAllowList, null, 2)}`, 400)
}
// check email regex
if (settings.enableEmailCheckRegex && settings.emailCheckRegex) {
try {
const regex = new RegExp(settings.emailCheckRegex);
if (!regex.test(email)) {
return c.text(`${msgs.UserEmailNotMatchRegexMsg}: /${settings.emailCheckRegex}/`, 400)
}
} catch (e) {
console.error("Failed to check user email regex", e);
}
}
if (!settings.verifyMailSender) {
return c.text(msgs.VerifyMailSenderNotSetMsg, 400)
}
@@ -82,6 +93,17 @@ export default {
) {
return c.text(`${msgs.UserMailDomainMustInMsg} ${JSON.stringify(settings.mailAllowList, null, 2)}`, 400)
}
// check email regex
if (settings.enableEmailCheckRegex && settings.emailCheckRegex) {
try {
const regex = new RegExp(settings.emailCheckRegex);
if (!regex.test(email)) {
return c.text(`${msgs.UserEmailNotMatchRegexMsg}: /${settings.emailCheckRegex}/`, 400)
}
} catch (e) {
console.error("Failed to check user email regex", e);
}
}
// check code
if (settings.enableMailVerify) {
const verifyCode = await c.env.KV.get(`temp-mail:${email}`)