diff --git a/model/common.go b/model/common.go
index 018a8642..c85c19ab 100644
--- a/model/common.go
+++ b/model/common.go
@@ -140,3 +140,13 @@ func assembleSumSelectStr(selectStr string) string {
return sumSelectStr
}
+
+func RecordExists(table interface{}, fieldName string, fieldValue interface{}, excludeID interface{}) bool {
+ var count int64
+ query := DB.Model(table).Where(fmt.Sprintf("%s = ?", fieldName), fieldValue)
+ if excludeID != nil {
+ query = query.Not("id", excludeID)
+ }
+ query.Count(&count)
+ return count > 0
+}
diff --git a/model/user.go b/model/user.go
index 3adb7b83..9190efc5 100644
--- a/model/user.go
+++ b/model/user.go
@@ -5,6 +5,7 @@ import (
"fmt"
"one-api/common"
"strings"
+ "time"
"gorm.io/gorm"
)
@@ -12,25 +13,26 @@ import (
// User if you add sensitive fields, don't forget to clean them in setupLogin function.
// Otherwise, the sensitive information will be saved on local storage in plain text!
type User struct {
- Id int `json:"id"`
- Username string `json:"username" gorm:"unique;index" validate:"max=12"`
- Password string `json:"password" gorm:"not null;" validate:"min=8,max=20"`
- DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
- Role int `json:"role" gorm:"type:int;default:1"` // admin, common
- Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
- Email string `json:"email" gorm:"index" validate:"max=50"`
- GitHubId string `json:"github_id" gorm:"column:github_id;index"`
- WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
- TelegramId int64 `json:"telegram_id" gorm:"bigint,column:telegram_id;default:0;"`
- VerificationCode string `json:"verification_code" gorm:"-:all"` // this field is only for Email verification, don't save it to database!
- AccessToken string `json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"` // this token is for system management
- Quota int `json:"quota" gorm:"type:int;default:0"`
- UsedQuota int `json:"used_quota" gorm:"type:int;default:0;column:used_quota"` // used quota
- RequestCount int `json:"request_count" gorm:"type:int;default:0;"` // request number
- Group string `json:"group" gorm:"type:varchar(32);default:'default'"`
- AffCode string `json:"aff_code" gorm:"type:varchar(32);column:aff_code;uniqueIndex"`
- InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"`
- CreatedTime int64 `json:"created_time" gorm:"bigint"`
+ Id int `json:"id"`
+ Username string `json:"username" gorm:"unique;index" validate:"max=12"`
+ Password string `json:"password" gorm:"not null;" validate:"min=8,max=20"`
+ DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
+ Role int `json:"role" gorm:"type:int;default:1"` // admin, common
+ Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
+ Email string `json:"email" gorm:"index" validate:"max=50"`
+ GitHubId string `json:"github_id" gorm:"column:github_id;index"`
+ WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
+ TelegramId int64 `json:"telegram_id" gorm:"bigint,column:telegram_id;default:0;"`
+ VerificationCode string `json:"verification_code" gorm:"-:all"` // this field is only for Email verification, don't save it to database!
+ AccessToken string `json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"` // this token is for system management
+ Quota int `json:"quota" gorm:"type:int;default:0"`
+ UsedQuota int `json:"used_quota" gorm:"type:int;default:0;column:used_quota"` // used quota
+ RequestCount int `json:"request_count" gorm:"type:int;default:0;"` // request number
+ Group string `json:"group" gorm:"type:varchar(32);default:'default'"`
+ AffCode string `json:"aff_code" gorm:"type:varchar(32);column:aff_code;uniqueIndex"`
+ InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"`
+ CreatedTime int64 `json:"created_time" gorm:"bigint"`
+ DeletedAt *time.Time `gorm:"index"`
}
type UserUpdates func(*User)
@@ -102,6 +104,9 @@ func DeleteUserById(id int) (err error) {
}
func (user *User) Insert(inviterId int) error {
+ if RecordExists(&User{}, "username", user.Username, nil) {
+ return errors.New("用户名已存在!")
+ }
var err error
if user.Password != "" {
user.Password, err = common.Password2Hash(user.Password)
@@ -134,6 +139,9 @@ func (user *User) Insert(inviterId int) error {
}
func (user *User) Update(updatePassword bool) error {
+ if RecordExists(&User{}, "username", user.Username, user.Id) {
+ return errors.New("用户名已存在!")
+ }
var err error
if updatePassword {
user.Password, err = common.Password2Hash(user.Password)
diff --git a/router/api-router.go b/router/api-router.go
index d1fef864..c2b2fcc8 100644
--- a/router/api-router.go
+++ b/router/api-router.go
@@ -42,7 +42,7 @@ func SetApiRouter(router *gin.Engine) {
selfRoute.GET("/dashboard", controller.GetUserDashboard)
selfRoute.GET("/self", controller.GetSelf)
selfRoute.PUT("/self", controller.UpdateSelf)
- selfRoute.DELETE("/self", controller.DeleteSelf)
+ // selfRoute.DELETE("/self", controller.DeleteSelf)
selfRoute.GET("/token", controller.GenerateAccessToken)
selfRoute.GET("/aff", controller.GetAffCode)
selfRoute.POST("/topup", controller.TopUp)
diff --git a/web/src/views/Profile/index.js b/web/src/views/Profile/index.js
index bdf4e080..44b4aaf8 100644
--- a/web/src/views/Profile/index.js
+++ b/web/src/views/Profile/index.js
@@ -1,21 +1,6 @@
import { useState, useEffect } from 'react';
import UserCard from 'ui-component/cards/UserCard';
-import {
- Card,
- Button,
- InputLabel,
- FormControl,
- OutlinedInput,
- Stack,
- Alert,
- Dialog,
- DialogTitle,
- DialogContent,
- DialogActions,
- Divider,
- Chip,
- Typography
-} from '@mui/material';
+import { Card, Button, InputLabel, FormControl, OutlinedInput, Stack, Alert, Divider, Chip, Typography } from '@mui/material';
import Grid from '@mui/material/Unstable_Grid2';
import SubCard from 'ui-component/cards/SubCard';
import { IconBrandWechat, IconBrandGithub, IconMail, IconBrandTelegram } from '@tabler/icons-react';
@@ -38,7 +23,6 @@ const validationSchema = Yup.object().shape({
export default function Profile() {
const [inputs, setInputs] = useState([]);
- const [showAccountDeleteModal, setShowAccountDeleteModal] = useState(false);
const [turnstileEnabled, setTurnstileEnabled] = useState(false);
const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
const [turnstileToken, setTurnstileToken] = useState('');
@@ -284,41 +268,11 @@ export default function Profile() {
{inputs.access_token ? '重置访问令牌' : '生成访问令牌'}
-
-
-
-
-