🔀 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 { 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"` 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"` Type int `json:"type" gorm:"index:idx_created_at_type"`
Content string `json:"content"` Content string `json:"content"`
Username string `json:"username" gorm:"index:index_username_model_name,priority:2;default:''"` Username string `json:"username" gorm:"index:index_username_model_name,priority:2;default:''"`

View File

@ -3,8 +3,9 @@ package model
import ( import (
"errors" "errors"
"fmt" "fmt"
"gorm.io/gorm"
"one-api/common" "one-api/common"
"gorm.io/gorm"
) )
type Token struct { type Token struct {
@ -38,39 +39,43 @@ func ValidateUserToken(key string) (token *Token, err error) {
return nil, errors.New("未提供令牌") return nil, errors.New("未提供令牌")
} }
token, err = CacheGetTokenByKey(key) token, err = CacheGetTokenByKey(key)
if err == nil { if err != nil {
if token.Status == common.TokenStatusExhausted { common.SysError("CacheGetTokenByKey failed: " + err.Error())
return nil, errors.New("该令牌额度已用尽") if errors.Is(err, gorm.ErrRecordNotFound) {
} else if token.Status == common.TokenStatusExpired { return nil, errors.New("无效的令牌")
return nil, errors.New("该令牌已过期")
} }
if token.Status != common.TokenStatusEnabled { return nil, errors.New("令牌验证失败")
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("无效的令牌") 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) { func GetTokenByIds(id int, userId int) (*Token, error) {

View File

@ -139,7 +139,15 @@ func (user *User) ValidateAndFill() (err error) {
if user.Username == "" || password == "" { if user.Username == "" || password == "" {
return errors.New("用户名或密码为空") 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) okay := common.ValidatePasswordAndHash(password, user.Password)
if !okay || user.Status != common.UserStatusEnabled { if !okay || user.Status != common.UserStatusEnabled {
return errors.New("用户名或密码错误,或用户已被封禁") return errors.New("用户名或密码错误,或用户已被封禁")

View File

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

View File

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

View File

@ -38,9 +38,6 @@ const Sidebar = ({ drawerOpen, drawerToggle, window }) => {
> >
<MenuList /> <MenuList />
<MenuCard /> <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> </PerfectScrollbar>
</BrowserView> </BrowserView>
<MobileView> <MobileView>

View File

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

View File

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

View File

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

View File

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

View File

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