feat: support email domain restriction
This commit is contained in:
parent
ec88c0c240
commit
7c011066d1
@ -42,6 +42,17 @@ var WeChatAuthEnabled = false
|
||||
var TurnstileCheckEnabled = false
|
||||
var RegisterEnabled = true
|
||||
|
||||
var EmailDomainRestrictionEnabled = false
|
||||
var RestrictedEmailDomains = []string{
|
||||
"gmail.com",
|
||||
"163.com",
|
||||
"qq.com",
|
||||
"outlook.com",
|
||||
"hotmail.com",
|
||||
"icloud.com",
|
||||
"yahoo.com",
|
||||
}
|
||||
|
||||
var LogConsumeEnabled = true
|
||||
|
||||
var SMTPServer = ""
|
||||
|
@ -3,10 +3,12 @@ package controller
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"one-api/common"
|
||||
"one-api/model"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetStatus(c *gin.Context) {
|
||||
@ -78,6 +80,20 @@ 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])
|
||||
|
||||
if !allowed {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "该邮箱地址不允许注册",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if model.IsEmailAlreadyTaken(email) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
|
@ -2,11 +2,12 @@ package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"one-api/common"
|
||||
"one-api/model"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetOptions(c *gin.Context) {
|
||||
@ -49,6 +50,14 @@ func UpdateOption(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
case "EmailDomainRestrictionEnabled":
|
||||
if option.Value == "true" && len(common.RestrictedEmailDomains) == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法启用邮箱域名限制,请先填入限制的邮箱域名!",
|
||||
})
|
||||
return
|
||||
}
|
||||
case "WeChatAuthEnabled":
|
||||
if option.Value == "true" && common.WeChatServerAddress == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
@ -39,6 +39,8 @@ func InitOptionMap() {
|
||||
common.OptionMap["DisplayInCurrencyEnabled"] = strconv.FormatBool(common.DisplayInCurrencyEnabled)
|
||||
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["SMTPServer"] = ""
|
||||
common.OptionMap["SMTPFrom"] = ""
|
||||
common.OptionMap["SMTPPort"] = strconv.Itoa(common.SMTPPort)
|
||||
@ -141,6 +143,8 @@ func updateOptionMap(key string, value string) (err error) {
|
||||
common.TurnstileCheckEnabled = boolValue
|
||||
case "RegisterEnabled":
|
||||
common.RegisterEnabled = boolValue
|
||||
case "EmailDomainRestrictionEnabled":
|
||||
common.EmailDomainRestrictionEnabled = boolValue
|
||||
case "AutomaticDisableChannelEnabled":
|
||||
common.AutomaticDisableChannelEnabled = boolValue
|
||||
case "ApproximateTokenEnabled":
|
||||
@ -154,6 +158,8 @@ func updateOptionMap(key string, value string) (err error) {
|
||||
}
|
||||
}
|
||||
switch key {
|
||||
case "RestrictedEmailDomains":
|
||||
common.RestrictedEmailDomains = strings.Split(value, ",")
|
||||
case "SMTPServer":
|
||||
common.SMTPServer = value
|
||||
case "SMTPPort":
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Divider, Form, Grid, Header, Message } from 'semantic-ui-react';
|
||||
import { API, removeTrailingSlash, showError, verifyJSON } from '../helpers';
|
||||
import { Button, Divider, Form, Grid, Header, Input, Message } from 'semantic-ui-react';
|
||||
import { API, removeTrailingSlash, showError } from '../helpers';
|
||||
|
||||
const SystemSetting = () => {
|
||||
let [inputs, setInputs] = useState({
|
||||
@ -26,9 +26,13 @@ const SystemSetting = () => {
|
||||
TurnstileSiteKey: '',
|
||||
TurnstileSecretKey: '',
|
||||
RegisterEnabled: '',
|
||||
EmailDomainRestrictionEnabled: '',
|
||||
RestrictedEmailDomains: ''
|
||||
});
|
||||
const [originInputs, setOriginInputs] = useState({});
|
||||
let [loading, setLoading] = useState(false);
|
||||
const [restrictedEmailDomains, setRestrictedEmailDomains] = useState([]);
|
||||
const [restrictedDomainInput, setRestrictedDomainInput] = useState('');
|
||||
|
||||
const getOptions = async () => {
|
||||
const res = await API.get('/api/option/');
|
||||
@ -38,8 +42,15 @@ const SystemSetting = () => {
|
||||
data.forEach((item) => {
|
||||
newInputs[item.key] = item.value;
|
||||
});
|
||||
setInputs(newInputs);
|
||||
setInputs({
|
||||
...newInputs,
|
||||
RestrictedEmailDomains: newInputs.RestrictedEmailDomains.split(',')
|
||||
});
|
||||
setOriginInputs(newInputs);
|
||||
|
||||
setRestrictedEmailDomains(newInputs.RestrictedEmailDomains.split(',').map((item) => {
|
||||
return { key: item, text: item, value: item };
|
||||
}));
|
||||
} else {
|
||||
showError(message);
|
||||
}
|
||||
@ -58,6 +69,7 @@ const SystemSetting = () => {
|
||||
case 'GitHubOAuthEnabled':
|
||||
case 'WeChatAuthEnabled':
|
||||
case 'TurnstileCheckEnabled':
|
||||
case 'EmailDomainRestrictionEnabled':
|
||||
case 'RegisterEnabled':
|
||||
value = inputs[key] === 'true' ? 'false' : 'true';
|
||||
break;
|
||||
@ -70,7 +82,12 @@ const SystemSetting = () => {
|
||||
});
|
||||
const { success, message } = res.data;
|
||||
if (success) {
|
||||
setInputs((inputs) => ({ ...inputs, [key]: value }));
|
||||
if (key === 'RestrictedEmailDomains') {
|
||||
value = value.split(',');
|
||||
}
|
||||
setInputs((inputs) => ({
|
||||
...inputs, [key]: value
|
||||
}));
|
||||
} else {
|
||||
showError(message);
|
||||
}
|
||||
@ -88,7 +105,8 @@ const SystemSetting = () => {
|
||||
name === 'WeChatServerToken' ||
|
||||
name === 'WeChatAccountQRCodeImageURL' ||
|
||||
name === 'TurnstileSiteKey' ||
|
||||
name === 'TurnstileSecretKey'
|
||||
name === 'TurnstileSecretKey' ||
|
||||
name === 'RestrictedEmailDomains'
|
||||
) {
|
||||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||
} else {
|
||||
@ -123,6 +141,12 @@ const SystemSetting = () => {
|
||||
) {
|
||||
await updateOption('SMTPToken', inputs.SMTPToken);
|
||||
}
|
||||
if (
|
||||
originInputs['RestrictedEmailDomains'] !== inputs.RestrictedEmailDomains.join(',') &&
|
||||
inputs.SMTPToken !== ''
|
||||
) {
|
||||
await updateOption('RestrictedEmailDomains', inputs.RestrictedEmailDomains.join(','));
|
||||
}
|
||||
};
|
||||
|
||||
const submitWeChat = async () => {
|
||||
@ -282,12 +306,58 @@ const SystemSetting = () => {
|
||||
label='SMTP 访问凭证'
|
||||
name='SMTPToken'
|
||||
onChange={handleInputChange}
|
||||
type='password'
|
||||
autoComplete='new-password'
|
||||
value={inputs.SMTPToken}
|
||||
checked={inputs.RegisterEnabled === 'true'}
|
||||
placeholder='敏感信息不会发送到前端显示'
|
||||
/>
|
||||
</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>
|
||||
<Divider />
|
||||
<Header as='h3'>
|
||||
|
Loading…
Reference in New Issue
Block a user