From 2ea40b63c8afed8168dd79940168aa073a0a11b2 Mon Sep 17 00:00:00 2001 From: JustSong Date: Sun, 30 Jul 2023 12:43:21 +0800 Subject: [PATCH] chore: update implementation --- README.md | 2 +- common/constants.go | 4 +- controller/misc.go | 14 +-- controller/option.go | 2 +- model/option.go | 6 +- web/src/components/SystemSetting.js | 132 ++++++++++++++++------------ 6 files changed, 92 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index e01ea7d9..f32495b2 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用 19. 支持通过系统访问令牌访问管理 API。 20. 支持 Cloudflare Turnstile 用户校验。 21. 支持用户管理,支持**多种用户登录注册方式**: - + 邮箱登录注册以及通过邮箱进行密码重置。 + + 邮箱登录注册(支持注册邮箱白名单)以及通过邮箱进行密码重置。 + [GitHub 开放授权](https://github.com/settings/applications/new)。 + 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。 diff --git a/common/constants.go b/common/constants.go index 11a07f0b..eaaca803 100644 --- a/common/constants.go +++ b/common/constants.go @@ -43,14 +43,16 @@ var TurnstileCheckEnabled = false var RegisterEnabled = true var EmailDomainRestrictionEnabled = false -var RestrictedEmailDomains = []string{ +var EmailDomainWhitelist = []string{ "gmail.com", "163.com", + "126.com", "qq.com", "outlook.com", "hotmail.com", "icloud.com", "yahoo.com", + "foxmail.com", } var LogConsumeEnabled = true diff --git a/controller/misc.go b/controller/misc.go index a8c98a44..2bcbb41f 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -81,15 +81,17 @@ func SendEmailVerification(c *gin.Context) { return } if common.EmailDomainRestrictionEnabled { - allowedEmailDomains := common.RestrictedEmailDomains - - // Check if email suffix is allowed - allowed := strings.Contains(strings.Join(allowedEmailDomains, ","), strings.Split(email, "@")[1]) - + allowed := false + for _, domain := range common.EmailDomainWhitelist { + if strings.HasSuffix(email, "@"+domain) { + allowed = true + break + } + } if !allowed { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该邮箱地址不允许注册", + "message": "管理员启用了邮箱域名白名单,您的邮箱地址的域名不在白名单中", }) return } diff --git a/controller/option.go b/controller/option.go index a176f9dd..9cf4ff1b 100644 --- a/controller/option.go +++ b/controller/option.go @@ -51,7 +51,7 @@ func UpdateOption(c *gin.Context) { return } case "EmailDomainRestrictionEnabled": - if option.Value == "true" && len(common.RestrictedEmailDomains) == 0 { + if option.Value == "true" && len(common.EmailDomainWhitelist) == 0 { c.JSON(http.StatusOK, gin.H{ "success": false, "message": "无法启用邮箱域名限制,请先填入限制的邮箱域名!", diff --git a/model/option.go b/model/option.go index 3b464f54..4ef4d260 100644 --- a/model/option.go +++ b/model/option.go @@ -40,7 +40,7 @@ func InitOptionMap() { common.OptionMap["DisplayTokenStatEnabled"] = strconv.FormatBool(common.DisplayTokenStatEnabled) common.OptionMap["ChannelDisableThreshold"] = strconv.FormatFloat(common.ChannelDisableThreshold, 'f', -1, 64) common.OptionMap["EmailDomainRestrictionEnabled"] = strconv.FormatBool(common.EmailDomainRestrictionEnabled) - common.OptionMap["RestrictedEmailDomains"] = strings.Join(common.RestrictedEmailDomains, ",") + common.OptionMap["EmailDomainWhitelist"] = strings.Join(common.EmailDomainWhitelist, ",") common.OptionMap["SMTPServer"] = "" common.OptionMap["SMTPFrom"] = "" common.OptionMap["SMTPPort"] = strconv.Itoa(common.SMTPPort) @@ -158,8 +158,8 @@ func updateOptionMap(key string, value string) (err error) { } } switch key { - case "RestrictedEmailDomains": - common.RestrictedEmailDomains = strings.Split(value, ",") + case "EmailDomainWhitelist": + common.EmailDomainWhitelist = strings.Split(value, ",") case "SMTPServer": common.SMTPServer = value case "SMTPPort": diff --git a/web/src/components/SystemSetting.js b/web/src/components/SystemSetting.js index 01af5801..88c82204 100644 --- a/web/src/components/SystemSetting.js +++ b/web/src/components/SystemSetting.js @@ -27,11 +27,11 @@ const SystemSetting = () => { TurnstileSecretKey: '', RegisterEnabled: '', EmailDomainRestrictionEnabled: '', - RestrictedEmailDomains: '' + EmailDomainWhitelist: '' }); const [originInputs, setOriginInputs] = useState({}); let [loading, setLoading] = useState(false); - const [restrictedEmailDomains, setRestrictedEmailDomains] = useState([]); + const [EmailDomainWhitelist, setEmailDomainWhitelist] = useState([]); const [restrictedDomainInput, setRestrictedDomainInput] = useState(''); const getOptions = async () => { @@ -44,11 +44,11 @@ const SystemSetting = () => { }); setInputs({ ...newInputs, - RestrictedEmailDomains: newInputs.RestrictedEmailDomains.split(',') + EmailDomainWhitelist: newInputs.EmailDomainWhitelist.split(',') }); setOriginInputs(newInputs); - setRestrictedEmailDomains(newInputs.RestrictedEmailDomains.split(',').map((item) => { + setEmailDomainWhitelist(newInputs.EmailDomainWhitelist.split(',').map((item) => { return { key: item, text: item, value: item }; })); } else { @@ -82,7 +82,7 @@ const SystemSetting = () => { }); const { success, message } = res.data; if (success) { - if (key === 'RestrictedEmailDomains') { + if (key === 'EmailDomainWhitelist') { value = value.split(','); } setInputs((inputs) => ({ @@ -106,7 +106,7 @@ const SystemSetting = () => { name === 'WeChatAccountQRCodeImageURL' || name === 'TurnstileSiteKey' || name === 'TurnstileSecretKey' || - name === 'RestrictedEmailDomains' + name === 'EmailDomainWhitelist' ) { setInputs((inputs) => ({ ...inputs, [name]: value })); } else { @@ -141,11 +141,15 @@ const SystemSetting = () => { ) { await updateOption('SMTPToken', inputs.SMTPToken); } + }; + + + const submitEmailDomainWhitelist = async () => { if ( - originInputs['RestrictedEmailDomains'] !== inputs.RestrictedEmailDomains.join(',') && + originInputs['EmailDomainWhitelist'] !== inputs.EmailDomainWhitelist.join(',') && inputs.SMTPToken !== '' ) { - await updateOption('RestrictedEmailDomains', inputs.RestrictedEmailDomains.join(',')); + await updateOption('EmailDomainWhitelist', inputs.EmailDomainWhitelist.join(',')); } }; @@ -197,6 +201,22 @@ const SystemSetting = () => { } }; + const submitNewRestrictedDomain = () => { + const localDomainList = inputs.EmailDomainWhitelist; + if (restrictedDomainInput !== '' && !localDomainList.includes(restrictedDomainInput)) { + setRestrictedDomainInput(''); + setInputs({ + ...inputs, + EmailDomainWhitelist: [...localDomainList, restrictedDomainInput], + }); + setEmailDomainWhitelist([...EmailDomainWhitelist, { + key: restrictedDomainInput, + text: restrictedDomainInput, + value: restrictedDomainInput, + }]); + } + } + return ( @@ -263,6 +283,54 @@ const SystemSetting = () => { /> +
+ 配置邮箱域名白名单 + 用以防止恶意用户利用临时邮箱批量注册 +
+ + + + + + { + submitNewRestrictedDomain(); + }}>填入 + } + onKeyDown={(e) => { + if (e.key === 'Enter') { + submitNewRestrictedDomain(); + } + }} + autoComplete='new-password' + placeholder='输入新的允许的邮箱域名' + value={restrictedDomainInput} + onChange={(e, { value }) => { + setRestrictedDomainInput(value); + }} + /> + + 保存邮箱域名白名单设置 +
配置 SMTP 用以支持系统的邮件发送 @@ -312,54 +380,6 @@ const SystemSetting = () => { placeholder='敏感信息不会发送到前端显示' /> - - - - - - { - const localDomainList = inputs.RestrictedEmailDomains; - if (restrictedDomainInput !== '' && !localDomainList.includes(restrictedDomainInput)) { - setRestrictedDomainInput(''); - setInputs({ - ...inputs, - RestrictedEmailDomains: [...localDomainList, restrictedDomainInput], - }); - setRestrictedEmailDomains([...restrictedEmailDomains, { - key: restrictedDomainInput, - text: restrictedDomainInput, - value: restrictedDomainInput, - }]); - } - }}>填入 - } - placeholder='输入受限电子邮件域名' - value={restrictedDomainInput} - onChange={(e, { value }) => { - setRestrictedDomainInput(value); - }} - /> - 保存 SMTP 设置