Skip to content

Commit

Permalink
feat: 添加令牌ip白名单功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Calcium-Ion committed Sep 17, 2024
1 parent feb1d76 commit f505afd
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 3 deletions.
5 changes: 5 additions & 0 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ func IntMax(a int, b int) int {
}
}

func IsIP(s string) bool {
ip := net.ParseIP(s)
return ip != nil
}

func GetUUID() string {
code := uuid.New().String()
code = strings.Replace(code, "-", "", -1)
Expand Down
2 changes: 2 additions & 0 deletions controller/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func AddToken(c *gin.Context) {
UnlimitedQuota: token.UnlimitedQuota,
ModelLimitsEnabled: token.ModelLimitsEnabled,
ModelLimits: token.ModelLimits,
AllowIps: token.AllowIps,
}
err = cleanToken.Insert()
if err != nil {
Expand Down Expand Up @@ -221,6 +222,7 @@ func UpdateToken(c *gin.Context) {
cleanToken.UnlimitedQuota = token.UnlimitedQuota
cleanToken.ModelLimitsEnabled = token.ModelLimitsEnabled
cleanToken.ModelLimits = token.ModelLimits
cleanToken.AllowIps = token.AllowIps
}
err = cleanToken.Update()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func TokenAuth() func(c *gin.Context) {
} else {
c.Set("token_model_limit_enabled", false)
}
c.Set("allow_ips", token.GetIpLimitsMap())
if len(parts) > 1 {
if model.IsAdmin(token.UserId) {
c.Set("specific_channel_id", parts[1])
Expand Down
8 changes: 8 additions & 0 deletions middleware/distributor.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ type ModelRequest struct {

func Distribute() func(c *gin.Context) {
return func(c *gin.Context) {
allowIpsMap := c.GetStringMap("allow_ips")
if len(allowIpsMap) != 0 {
clientIp := c.ClientIP()
if _, ok := allowIpsMap[clientIp]; !ok {
abortWithOpenAiMessage(c, http.StatusForbidden, "您的 IP 不在令牌允许访问的列表中")
return
}
}
userId := c.GetInt("id")
var channel *model.Channel
channelId, ok := c.Get("specific_channel_id")
Expand Down
25 changes: 24 additions & 1 deletion model/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,33 @@ type Token struct {
UnlimitedQuota bool `json:"unlimited_quota" gorm:"default:false"`
ModelLimitsEnabled bool `json:"model_limits_enabled" gorm:"default:false"`
ModelLimits string `json:"model_limits" gorm:"type:varchar(1024);default:''"`
AllowIps *string `json:"allow_ips" gorm:"default:''"`
UsedQuota int `json:"used_quota" gorm:"default:0"` // used quota
DeletedAt gorm.DeletedAt `gorm:"index"`
}

func (token *Token) GetIpLimitsMap() map[string]any {
// delete empty spaces
//split with \n
ipLimitsMap := make(map[string]any)
if token.AllowIps == nil {
return ipLimitsMap
}
cleanIps := strings.ReplaceAll(*token.AllowIps, " ", "")
if cleanIps == "" {
return ipLimitsMap
}
ips := strings.Split(cleanIps, "\n")
for _, ip := range ips {
ip = strings.TrimSpace(ip)
ip = strings.ReplaceAll(ip, ",", "")
if common.IsIP(ip) {
ipLimitsMap[ip] = true
}
}
return ipLimitsMap
}

func GetAllUserTokens(userId int, startIdx int, num int) ([]*Token, error) {
var tokens []*Token
var err error
Expand Down Expand Up @@ -130,7 +153,7 @@ func (token *Token) Insert() error {
// Update Make sure your token's fields is completed, because this will update non-zero values
func (token *Token) Update() error {
var err error
err = DB.Model(token).Select("name", "status", "expired_time", "remain_quota", "unlimited_quota", "model_limits_enabled", "model_limits").Updates(token).Error
err = DB.Model(token).Select("name", "status", "expired_time", "remain_quota", "unlimited_quota", "model_limits_enabled", "model_limits", "allow_ips").Updates(token).Error
return err
}

Expand Down
19 changes: 17 additions & 2 deletions web/src/pages/Token/EditToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {
Select,
SideSheet,
Space,
Spin,
Typography,
Spin, TextArea,
Typography
} from '@douyinfe/semi-ui';
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
import { Divider } from 'semantic-ui-react';
Expand All @@ -34,6 +34,7 @@ const EditToken = (props) => {
unlimited_quota: false,
model_limits_enabled: false,
model_limits: [],
allow_ips: '',
};
const [inputs, setInputs] = useState(originInputs);
const {
Expand All @@ -43,6 +44,7 @@ const EditToken = (props) => {
unlimited_quota,
model_limits_enabled,
model_limits,
allow_ips
} = inputs;
// const [visible, setVisible] = useState(false);
const [models, setModels] = useState({});
Expand Down Expand Up @@ -374,6 +376,19 @@ const EditToken = (props) => {
</Button>
</div>
<Divider />
<div style={{ marginTop: 10 }}>
<Typography.Text>IP白名单(请勿过度信任此功能)</Typography.Text>
</div>
<TextArea
label='IP白名单'
name='allow_ips'
placeholder={'允许的IP,一行一个'}
onChange={(value) => {
handleInputChange('allow_ips', value);
}}
value={inputs.allow_ips}
style={{ fontFamily: 'JetBrains Mono, Consolas' }}
/>
<div style={{ marginTop: 10, display: 'flex' }}>
<Space>
<Checkbox
Expand Down

0 comments on commit f505afd

Please sign in to comment.