diff --git a/controller/user.go b/controller/user.go index f04f9ca..baae157 100644 --- a/controller/user.go +++ b/controller/user.go @@ -152,6 +152,21 @@ func Register(c *gin.Context) { return } } + exist, err := model.CheckUserExistOrDeleted(user.Username, user.Email) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return + } + if exist { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": "用户名已存在,或已注销", + }) + return + } affCode := user.AffCode // this code is the inviter's code, not the user's own code inviterId, _ := model.GetUserIdByAffCode(affCode) cleanUser := model.User{ @@ -525,7 +540,7 @@ func DeleteUser(c *gin.Context) { }) return } - err = model.DeleteUserById(id) + err = model.HardDeleteUserById(id) if err != nil { c.JSON(http.StatusOK, gin.H{ "success": true, diff --git a/model/user.go b/model/user.go index 422d268..e3c7dfc 100644 --- a/model/user.go +++ b/model/user.go @@ -11,26 +11,43 @@ 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"` - 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"` - AffCount int `json:"aff_count" gorm:"type:int;default:0;column:aff_count"` - AffQuota int `json:"aff_quota" gorm:"type:int;default:0;column:aff_quota"` // 邀请剩余额度 - AffHistoryQuota int `json:"aff_history_quota" gorm:"type:int;default:0;column:aff_history"` // 邀请历史额度 - InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"` + 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"` + 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"` + AffCount int `json:"aff_count" gorm:"type:int;default:0;column:aff_count"` + AffQuota int `json:"aff_quota" gorm:"type:int;default:0;column:aff_quota"` // 邀请剩余额度 + AffHistoryQuota int `json:"aff_history_quota" gorm:"type:int;default:0;column:aff_history"` // 邀请历史额度 + InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"` + DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"` +} + +// CheckUserExistOrDeleted check if user exist or deleted, if not exist, return false, nil, if deleted or exist, return true, nil +func CheckUserExistOrDeleted(username string, email string) (bool, error) { + var user User + err := DB.Unscoped().First(&user, "username = ? or email = ?", username, email).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + // not exist, return false, nil + return false, nil + } + // other error, return false, err + return false, err + } + // exist, return true, nil + return true, nil } func GetMaxUserId() int { @@ -40,7 +57,7 @@ func GetMaxUserId() int { } func GetAllUsers(startIdx int, num int) (users []*User, err error) { - err = DB.Order("id desc").Limit(num).Offset(startIdx).Omit("password").Find(&users).Error + err = DB.Unscoped().Order("id desc").Limit(num).Offset(startIdx).Omit("password").Find(&users).Error return users, err } @@ -80,6 +97,14 @@ func DeleteUserById(id int) (err error) { return user.Delete() } +func HardDeleteUserById(id int) error { + if id == 0 { + return errors.New("id 为空!") + } + err := DB.Unscoped().Delete(&User{}, "id = ?", id).Error + return err +} + func inviteUser(inviterId int) (err error) { user, err := GetUserById(inviterId, true) if err != nil { diff --git a/web/src/components/UsersTable.js b/web/src/components/UsersTable.js index 2608270..ffed3f3 100644 --- a/web/src/components/UsersTable.js +++ b/web/src/components/UsersTable.js @@ -72,32 +72,49 @@ const UsersTable = () => { }, { title: '状态', dataIndex: 'status', render: (text, record, index) => { return (
- {renderStatus(text)} + {record.deleted_at !== null? 已注销 : renderStatus(text)}
); }, }, { title: '', dataIndex: 'operate', render: (text, record, index) => (
- { - manageUser(record.username, 'promote', record) - }} - > - - - { - manageUser(record.username, 'demote', record) - }} - > - - + { + record.deleted_at !== null ? <>: + <> + { + manageUser(record.username, 'promote', record) + }} + > + + + { + manageUser(record.username, 'demote', record) + }} + > + + + {record.status === 1 ? + : + } + + + + } { @@ -108,17 +125,6 @@ const UsersTable = () => { > - {record.status === 1 ? - : - } -
), },];