🔀 sync: sync upstream
This commit is contained in:
parent
ef041e28a1
commit
45fd814d77
@ -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:''"`
|
||||||
|
@ -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) {
|
||||||
|
@ -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("用户名或密码错误,或用户已被封禁")
|
||||||
|
@ -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>
|
||||||
|
@ -121,7 +121,6 @@ const MenuCard = () => {
|
|||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
{/* <LinearProgressWithLabel value={80} /> */}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</CardStyle>
|
</CardStyle>
|
||||||
);
|
);
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
|
@ -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 && (
|
||||||
|
@ -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>
|
||||||
|
@ -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}>
|
||||||
|
Loading…
Reference in New Issue
Block a user