chore: update implementation
This commit is contained in:
parent
c401842906
commit
2ea40b63c8
@ -94,7 +94,7 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用
|
|||||||
19. 支持通过系统访问令牌访问管理 API。
|
19. 支持通过系统访问令牌访问管理 API。
|
||||||
20. 支持 Cloudflare Turnstile 用户校验。
|
20. 支持 Cloudflare Turnstile 用户校验。
|
||||||
21. 支持用户管理,支持**多种用户登录注册方式**:
|
21. 支持用户管理,支持**多种用户登录注册方式**:
|
||||||
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
+ 邮箱登录注册(支持注册邮箱白名单)以及通过邮箱进行密码重置。
|
||||||
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
||||||
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
||||||
|
|
||||||
|
@ -43,14 +43,16 @@ var TurnstileCheckEnabled = false
|
|||||||
var RegisterEnabled = true
|
var RegisterEnabled = true
|
||||||
|
|
||||||
var EmailDomainRestrictionEnabled = false
|
var EmailDomainRestrictionEnabled = false
|
||||||
var RestrictedEmailDomains = []string{
|
var EmailDomainWhitelist = []string{
|
||||||
"gmail.com",
|
"gmail.com",
|
||||||
"163.com",
|
"163.com",
|
||||||
|
"126.com",
|
||||||
"qq.com",
|
"qq.com",
|
||||||
"outlook.com",
|
"outlook.com",
|
||||||
"hotmail.com",
|
"hotmail.com",
|
||||||
"icloud.com",
|
"icloud.com",
|
||||||
"yahoo.com",
|
"yahoo.com",
|
||||||
|
"foxmail.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
var LogConsumeEnabled = true
|
var LogConsumeEnabled = true
|
||||||
|
@ -81,15 +81,17 @@ func SendEmailVerification(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if common.EmailDomainRestrictionEnabled {
|
if common.EmailDomainRestrictionEnabled {
|
||||||
allowedEmailDomains := common.RestrictedEmailDomains
|
allowed := false
|
||||||
|
for _, domain := range common.EmailDomainWhitelist {
|
||||||
// Check if email suffix is allowed
|
if strings.HasSuffix(email, "@"+domain) {
|
||||||
allowed := strings.Contains(strings.Join(allowedEmailDomains, ","), strings.Split(email, "@")[1])
|
allowed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if !allowed {
|
if !allowed {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": "该邮箱地址不允许注册",
|
"message": "管理员启用了邮箱域名白名单,您的邮箱地址的域名不在白名单中",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ func UpdateOption(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "EmailDomainRestrictionEnabled":
|
case "EmailDomainRestrictionEnabled":
|
||||||
if option.Value == "true" && len(common.RestrictedEmailDomains) == 0 {
|
if option.Value == "true" && len(common.EmailDomainWhitelist) == 0 {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": "无法启用邮箱域名限制,请先填入限制的邮箱域名!",
|
"message": "无法启用邮箱域名限制,请先填入限制的邮箱域名!",
|
||||||
|
@ -40,7 +40,7 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["DisplayTokenStatEnabled"] = strconv.FormatBool(common.DisplayTokenStatEnabled)
|
common.OptionMap["DisplayTokenStatEnabled"] = strconv.FormatBool(common.DisplayTokenStatEnabled)
|
||||||
common.OptionMap["ChannelDisableThreshold"] = strconv.FormatFloat(common.ChannelDisableThreshold, 'f', -1, 64)
|
common.OptionMap["ChannelDisableThreshold"] = strconv.FormatFloat(common.ChannelDisableThreshold, 'f', -1, 64)
|
||||||
common.OptionMap["EmailDomainRestrictionEnabled"] = strconv.FormatBool(common.EmailDomainRestrictionEnabled)
|
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["SMTPServer"] = ""
|
||||||
common.OptionMap["SMTPFrom"] = ""
|
common.OptionMap["SMTPFrom"] = ""
|
||||||
common.OptionMap["SMTPPort"] = strconv.Itoa(common.SMTPPort)
|
common.OptionMap["SMTPPort"] = strconv.Itoa(common.SMTPPort)
|
||||||
@ -158,8 +158,8 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
case "RestrictedEmailDomains":
|
case "EmailDomainWhitelist":
|
||||||
common.RestrictedEmailDomains = strings.Split(value, ",")
|
common.EmailDomainWhitelist = strings.Split(value, ",")
|
||||||
case "SMTPServer":
|
case "SMTPServer":
|
||||||
common.SMTPServer = value
|
common.SMTPServer = value
|
||||||
case "SMTPPort":
|
case "SMTPPort":
|
||||||
|
@ -27,11 +27,11 @@ const SystemSetting = () => {
|
|||||||
TurnstileSecretKey: '',
|
TurnstileSecretKey: '',
|
||||||
RegisterEnabled: '',
|
RegisterEnabled: '',
|
||||||
EmailDomainRestrictionEnabled: '',
|
EmailDomainRestrictionEnabled: '',
|
||||||
RestrictedEmailDomains: ''
|
EmailDomainWhitelist: ''
|
||||||
});
|
});
|
||||||
const [originInputs, setOriginInputs] = useState({});
|
const [originInputs, setOriginInputs] = useState({});
|
||||||
let [loading, setLoading] = useState(false);
|
let [loading, setLoading] = useState(false);
|
||||||
const [restrictedEmailDomains, setRestrictedEmailDomains] = useState([]);
|
const [EmailDomainWhitelist, setEmailDomainWhitelist] = useState([]);
|
||||||
const [restrictedDomainInput, setRestrictedDomainInput] = useState('');
|
const [restrictedDomainInput, setRestrictedDomainInput] = useState('');
|
||||||
|
|
||||||
const getOptions = async () => {
|
const getOptions = async () => {
|
||||||
@ -44,11 +44,11 @@ const SystemSetting = () => {
|
|||||||
});
|
});
|
||||||
setInputs({
|
setInputs({
|
||||||
...newInputs,
|
...newInputs,
|
||||||
RestrictedEmailDomains: newInputs.RestrictedEmailDomains.split(',')
|
EmailDomainWhitelist: newInputs.EmailDomainWhitelist.split(',')
|
||||||
});
|
});
|
||||||
setOriginInputs(newInputs);
|
setOriginInputs(newInputs);
|
||||||
|
|
||||||
setRestrictedEmailDomains(newInputs.RestrictedEmailDomains.split(',').map((item) => {
|
setEmailDomainWhitelist(newInputs.EmailDomainWhitelist.split(',').map((item) => {
|
||||||
return { key: item, text: item, value: item };
|
return { key: item, text: item, value: item };
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
@ -82,7 +82,7 @@ const SystemSetting = () => {
|
|||||||
});
|
});
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
if (key === 'RestrictedEmailDomains') {
|
if (key === 'EmailDomainWhitelist') {
|
||||||
value = value.split(',');
|
value = value.split(',');
|
||||||
}
|
}
|
||||||
setInputs((inputs) => ({
|
setInputs((inputs) => ({
|
||||||
@ -106,7 +106,7 @@ const SystemSetting = () => {
|
|||||||
name === 'WeChatAccountQRCodeImageURL' ||
|
name === 'WeChatAccountQRCodeImageURL' ||
|
||||||
name === 'TurnstileSiteKey' ||
|
name === 'TurnstileSiteKey' ||
|
||||||
name === 'TurnstileSecretKey' ||
|
name === 'TurnstileSecretKey' ||
|
||||||
name === 'RestrictedEmailDomains'
|
name === 'EmailDomainWhitelist'
|
||||||
) {
|
) {
|
||||||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||||
} else {
|
} else {
|
||||||
@ -141,11 +141,15 @@ const SystemSetting = () => {
|
|||||||
) {
|
) {
|
||||||
await updateOption('SMTPToken', inputs.SMTPToken);
|
await updateOption('SMTPToken', inputs.SMTPToken);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const submitEmailDomainWhitelist = async () => {
|
||||||
if (
|
if (
|
||||||
originInputs['RestrictedEmailDomains'] !== inputs.RestrictedEmailDomains.join(',') &&
|
originInputs['EmailDomainWhitelist'] !== inputs.EmailDomainWhitelist.join(',') &&
|
||||||
inputs.SMTPToken !== ''
|
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 (
|
return (
|
||||||
<Grid columns={1}>
|
<Grid columns={1}>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
@ -263,6 +283,54 @@ const SystemSetting = () => {
|
|||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
配置邮箱域名白名单
|
||||||
|
<Header.Subheader>用以防止恶意用户利用临时邮箱批量注册</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Form.Group widths={3}>
|
||||||
|
<Form.Checkbox
|
||||||
|
label='启用邮箱域名白名单'
|
||||||
|
name='EmailDomainRestrictionEnabled'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
checked={inputs.EmailDomainRestrictionEnabled === 'true'}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group widths={2}>
|
||||||
|
<Form.Dropdown
|
||||||
|
label='允许的邮箱域名'
|
||||||
|
placeholder='允许的邮箱域名'
|
||||||
|
name='EmailDomainWhitelist'
|
||||||
|
required
|
||||||
|
fluid
|
||||||
|
multiple
|
||||||
|
selection
|
||||||
|
onChange={handleInputChange}
|
||||||
|
value={inputs.EmailDomainWhitelist}
|
||||||
|
autoComplete='new-password'
|
||||||
|
options={EmailDomainWhitelist}
|
||||||
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='添加新的允许的邮箱域名'
|
||||||
|
action={
|
||||||
|
<Button type='button' onClick={() => {
|
||||||
|
submitNewRestrictedDomain();
|
||||||
|
}}>填入</Button>
|
||||||
|
}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
submitNewRestrictedDomain();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
autoComplete='new-password'
|
||||||
|
placeholder='输入新的允许的邮箱域名'
|
||||||
|
value={restrictedDomainInput}
|
||||||
|
onChange={(e, { value }) => {
|
||||||
|
setRestrictedDomainInput(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Button onClick={submitEmailDomainWhitelist}>保存邮箱域名白名单设置</Form.Button>
|
||||||
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
配置 SMTP
|
配置 SMTP
|
||||||
<Header.Subheader>用以支持系统的邮件发送</Header.Subheader>
|
<Header.Subheader>用以支持系统的邮件发送</Header.Subheader>
|
||||||
@ -312,54 +380,6 @@ const SystemSetting = () => {
|
|||||||
placeholder='敏感信息不会发送到前端显示'
|
placeholder='敏感信息不会发送到前端显示'
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Form.Group widths={3}>
|
|
||||||
<Form.Checkbox
|
|
||||||
label='电子邮件域名限制'
|
|
||||||
name='EmailDomainRestrictionEnabled'
|
|
||||||
onChange={handleInputChange}
|
|
||||||
checked={inputs.EmailDomainRestrictionEnabled === 'true'}
|
|
||||||
/>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group widths={3}>
|
|
||||||
<Form.Dropdown
|
|
||||||
label='受限电子邮件域名'
|
|
||||||
placeholder='受限电子邮件域名'
|
|
||||||
name='RestrictedEmailDomains'
|
|
||||||
required
|
|
||||||
fluid
|
|
||||||
multiple
|
|
||||||
selection
|
|
||||||
onChange={handleInputChange}
|
|
||||||
value={inputs.RestrictedEmailDomains}
|
|
||||||
autoComplete='new-password'
|
|
||||||
options={restrictedEmailDomains}
|
|
||||||
/>
|
|
||||||
<Form.Input
|
|
||||||
label='添加受限电子邮件域名'
|
|
||||||
action={
|
|
||||||
<Button type='button' onClick={() => {
|
|
||||||
const localDomainList = inputs.RestrictedEmailDomains;
|
|
||||||
if (restrictedDomainInput !== '' && !localDomainList.includes(restrictedDomainInput)) {
|
|
||||||
setRestrictedDomainInput('');
|
|
||||||
setInputs({
|
|
||||||
...inputs,
|
|
||||||
RestrictedEmailDomains: [...localDomainList, restrictedDomainInput],
|
|
||||||
});
|
|
||||||
setRestrictedEmailDomains([...restrictedEmailDomains, {
|
|
||||||
key: restrictedDomainInput,
|
|
||||||
text: restrictedDomainInput,
|
|
||||||
value: restrictedDomainInput,
|
|
||||||
}]);
|
|
||||||
}
|
|
||||||
}}>填入</Button>
|
|
||||||
}
|
|
||||||
placeholder='输入受限电子邮件域名'
|
|
||||||
value={restrictedDomainInput}
|
|
||||||
onChange={(e, { value }) => {
|
|
||||||
setRestrictedDomainInput(value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Button onClick={submitSMTP}>保存 SMTP 设置</Form.Button>
|
<Form.Button onClick={submitSMTP}>保存 SMTP 设置</Form.Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
|
Loading…
Reference in New Issue
Block a user