🔀 sync: sync upstream

This commit is contained in:
Martial BE 2024-01-19 03:26:33 +08:00 committed by Buer
parent ef041e28a1
commit 45fd814d77
11 changed files with 57 additions and 48 deletions

View File

@ -9,9 +9,9 @@ import (
)
type Log struct {
Id int `json:"id;index:idx_created_at_id,priority:1"`
Id int `json:"id"`
UserId int `json:"user_id" gorm:"index"`
CreatedAt int64 `json:"created_at" gorm:"bigint;index:idx_created_at_id,priority:2;index:idx_created_at_type"`
CreatedAt int64 `json:"created_at" gorm:"bigint;index:idx_created_at_type"`
Type int `json:"type" gorm:"index:idx_created_at_type"`
Content string `json:"content"`
Username string `json:"username" gorm:"index:index_username_model_name,priority:2;default:''"`

View File

@ -3,8 +3,9 @@ package model
import (
"errors"
"fmt"
"gorm.io/gorm"
"one-api/common"
"gorm.io/gorm"
)
type Token struct {
@ -38,39 +39,43 @@ func ValidateUserToken(key string) (token *Token, err error) {
return nil, errors.New("未提供令牌")
}
token, err = CacheGetTokenByKey(key)
if err == nil {
if token.Status == common.TokenStatusExhausted {
return nil, errors.New("该令牌额度已用尽")
} else if token.Status == common.TokenStatusExpired {
return nil, errors.New("该令牌已过期")
if err != nil {
common.SysError("CacheGetTokenByKey failed: " + err.Error())
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("无效的令牌")
}
if token.Status != common.TokenStatusEnabled {
return nil, errors.New("该令牌状态不可用")
}
if token.ExpiredTime != -1 && token.ExpiredTime < common.GetTimestamp() {
if !common.RedisEnabled {
token.Status = common.TokenStatusExpired
err := token.SelectUpdate()
if err != nil {
common.SysError("failed to update token status" + err.Error())
}
}
return nil, errors.New("该令牌已过期")
}
if !token.UnlimitedQuota && token.RemainQuota <= 0 {
if !common.RedisEnabled {
// in this case, we can make sure the token is exhausted
token.Status = common.TokenStatusExhausted
err := token.SelectUpdate()
if err != nil {
common.SysError("failed to update token status" + err.Error())
}
}
return nil, errors.New("该令牌额度已用尽")
}
return token, nil
return nil, errors.New("令牌验证失败")
}
return nil, errors.New("无效的令牌")
if token.Status == common.TokenStatusExhausted {
return nil, errors.New("该令牌额度已用尽")
} else if token.Status == common.TokenStatusExpired {
return nil, errors.New("该令牌已过期")
}
if token.Status != common.TokenStatusEnabled {
return nil, errors.New("该令牌状态不可用")
}
if token.ExpiredTime != -1 && token.ExpiredTime < common.GetTimestamp() {
if !common.RedisEnabled {
token.Status = common.TokenStatusExpired
err := token.SelectUpdate()
if err != nil {
common.SysError("failed to update token status" + err.Error())
}
}
return nil, errors.New("该令牌已过期")
}
if !token.UnlimitedQuota && token.RemainQuota <= 0 {
if !common.RedisEnabled {
// in this case, we can make sure the token is exhausted
token.Status = common.TokenStatusExhausted
err := token.SelectUpdate()
if err != nil {
common.SysError("failed to update token status" + err.Error())
}
}
return nil, errors.New("该令牌额度已用尽")
}
return token, nil
}
func GetTokenByIds(id int, userId int) (*Token, error) {

View File

@ -139,7 +139,15 @@ func (user *User) ValidateAndFill() (err error) {
if user.Username == "" || password == "" {
return errors.New("用户名或密码为空")
}
DB.Where(User{Username: user.Username}).First(user)
err = DB.Where("username = ?", user.Username).First(user).Error
if err != nil {
// we must make sure check username firstly
// consider this case: a malicious user set his username as other's email
err := DB.Where("email = ?", user.Username).First(user).Error
if err != nil {
return errors.New("用户名或密码错误,或用户已被封禁")
}
}
okay := common.ValidatePasswordAndHash(password, user.Password)
if !okay || user.Status != common.UserStatusEnabled {
return errors.New("用户名或密码错误,或用户已被封禁")

View File

@ -157,7 +157,7 @@ const ProfileSection = () => {
<ListItemIcon>
<IconLogout stroke={1.5} size="1.3rem" />
</ListItemIcon>
<ListItemText primary={<Typography variant="body2">Logout</Typography>} />
<ListItemText primary={<Typography variant="body2">注销</Typography>} />
</ListItemButton>
</List>
</MainCard>

View File

@ -121,7 +121,6 @@ const MenuCard = () => {
/>
</ListItem>
</List>
{/* <LinearProgressWithLabel value={80} /> */}
</CardContent>
</CardStyle>
);

View File

@ -38,9 +38,6 @@ const Sidebar = ({ drawerOpen, drawerToggle, window }) => {
>
<MenuList />
<MenuCard />
<Stack direction="row" justifyContent="center" sx={{ mb: 2 }}>
<Chip label={process.env.REACT_APP_VERSION} disabled chipcolor="secondary" size="small" sx={{ cursor: 'pointer' }} />
</Stack>
</PerfectScrollbar>
</BrowserView>
<MobileView>

View File

@ -44,7 +44,7 @@ const Header = () => {
</Button>
) : (
<Button component={Link} variant="contained" to="/login" color="primary">
</Button>
)}
</Stack>

View File

@ -22,7 +22,7 @@ const panel = {
children: [
{
id: 'dashboard',
title: 'Dashboard',
title: '仪表盘',
type: 'item',
url: '/panel/dashboard',
icon: icons.IconDashboard,
@ -40,7 +40,7 @@ const panel = {
},
{
id: 'token',
title: 'Token',
title: '令牌',
type: 'item',
url: '/panel/token',
icon: icons.IconKey,

View File

@ -180,7 +180,7 @@ const LoginForm = ({ ...others }) => {
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
<form noValidate onSubmit={handleSubmit} {...others}>
<FormControl fullWidth error={Boolean(touched.username && errors.username)} sx={{ ...theme.typography.customInput }}>
<InputLabel htmlFor="outlined-adornment-username-login">用户名</InputLabel>
<InputLabel htmlFor="outlined-adornment-username-login">用户名/邮箱</InputLabel>
<OutlinedInput
id="outlined-adornment-username-login"
type="text"
@ -188,7 +188,7 @@ const LoginForm = ({ ...others }) => {
name="username"
onBlur={handleBlur}
onChange={handleChange}
label="用户名"
label="用户名/邮箱"
inputProps={{ autoComplete: 'username' }}
/>
{touched.username && errors.username && (

View File

@ -103,7 +103,7 @@ const EditModal = ({ open, tokenId, onCancel, onOk }) => {
return (
<Dialog open={open} onClose={onCancel} fullWidth maxWidth={'md'}>
<DialogTitle sx={{ margin: '0px', fontWeight: 700, lineHeight: '1.55556', padding: '24px', fontSize: '1.125rem' }}>
{tokenId ? '编辑Token' : '新建Token'}
{tokenId ? '编辑令牌' : '新建令牌'}
</DialogTitle>
<Divider />
<DialogContent>

View File

@ -158,7 +158,7 @@ export default function Token() {
return (
<>
<Stack direction="row" alignItems="center" justifyContent="space-between" mb={5}>
<Typography variant="h4">Token</Typography>
<Typography variant="h4">令牌</Typography>
<Button
variant="contained"
@ -168,7 +168,7 @@ export default function Token() {
}}
startIcon={<IconPlus />}
>
新建Token
新建令牌
</Button>
</Stack>
<Stack mb={5}>