mirror of
				https://github.com/linux-do/new-api.git
				synced 2025-11-04 21:33:41 +08:00 
			
		
		
		
	用户注销后禁止再次注册
This commit is contained in:
		@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -72,32 +72,49 @@ const UsersTable = () => {
 | 
			
		||||
    }, {
 | 
			
		||||
        title: '状态', dataIndex: 'status', render: (text, record, index) => {
 | 
			
		||||
            return (<div>
 | 
			
		||||
                {renderStatus(text)}
 | 
			
		||||
                {record.deleted_at !== null? <Tag color='red'>已注销</Tag> : renderStatus(text)}
 | 
			
		||||
            </div>);
 | 
			
		||||
        },
 | 
			
		||||
    }, {
 | 
			
		||||
        title: '', dataIndex: 'operate', render: (text, record, index) => (<div>
 | 
			
		||||
            <Popconfirm
 | 
			
		||||
                title="确定?"
 | 
			
		||||
                okType={'warning'}
 | 
			
		||||
                onConfirm={() => {
 | 
			
		||||
                    manageUser(record.username, 'promote', record)
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <Button theme='light' type='warning' style={{marginRight: 1}}>提升</Button>
 | 
			
		||||
            </Popconfirm>
 | 
			
		||||
            <Popconfirm
 | 
			
		||||
                title="确定?"
 | 
			
		||||
                okType={'warning'}
 | 
			
		||||
                onConfirm={() => {
 | 
			
		||||
                    manageUser(record.username, 'demote', record)
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <Button theme='light' type='secondary' style={{marginRight: 1}}>降级</Button>
 | 
			
		||||
            </Popconfirm>
 | 
			
		||||
            {
 | 
			
		||||
                record.deleted_at !== null ? <></>:
 | 
			
		||||
                    <>
 | 
			
		||||
                        <Popconfirm
 | 
			
		||||
                            title="确定?"
 | 
			
		||||
                            okType={'warning'}
 | 
			
		||||
                            onConfirm={() => {
 | 
			
		||||
                                manageUser(record.username, 'promote', record)
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                            <Button theme='light' type='warning' style={{marginRight: 1}}>提升</Button>
 | 
			
		||||
                        </Popconfirm>
 | 
			
		||||
                        <Popconfirm
 | 
			
		||||
                            title="确定?"
 | 
			
		||||
                            okType={'warning'}
 | 
			
		||||
                            onConfirm={() => {
 | 
			
		||||
                                manageUser(record.username, 'demote', record)
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                            <Button theme='light' type='secondary' style={{marginRight: 1}}>降级</Button>
 | 
			
		||||
                        </Popconfirm>
 | 
			
		||||
                        {record.status === 1 ?
 | 
			
		||||
                            <Button theme='light' type='warning' style={{marginRight: 1}} onClick={async () => {
 | 
			
		||||
                                manageUser(record.username, 'disable', record)
 | 
			
		||||
                            }}>禁用</Button> :
 | 
			
		||||
                            <Button theme='light' type='secondary' style={{marginRight: 1}} onClick={async () => {
 | 
			
		||||
                                manageUser(record.username, 'enable', record);
 | 
			
		||||
                            }} disabled={record.status === 3}>启用</Button>}
 | 
			
		||||
                        <Button theme='light' type='tertiary' style={{marginRight: 1}} onClick={() => {
 | 
			
		||||
                            setEditingUser(record);
 | 
			
		||||
                            setShowEditUser(true);
 | 
			
		||||
                        }}>编辑</Button>
 | 
			
		||||
                    </>
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            <Popconfirm
 | 
			
		||||
                title="确定是否要删除此用户?"
 | 
			
		||||
                content="此修改将不可逆"
 | 
			
		||||
                content="硬删除,此修改将不可逆"
 | 
			
		||||
                okType={'danger'}
 | 
			
		||||
                position={'left'}
 | 
			
		||||
                onConfirm={() => {
 | 
			
		||||
@@ -108,17 +125,6 @@ const UsersTable = () => {
 | 
			
		||||
            >
 | 
			
		||||
                <Button theme='light' type='danger' style={{marginRight: 1}}>删除</Button>
 | 
			
		||||
            </Popconfirm>
 | 
			
		||||
            {record.status === 1 ?
 | 
			
		||||
                <Button theme='light' type='warning' style={{marginRight: 1}} onClick={async () => {
 | 
			
		||||
                    manageUser(record.username, 'disable', record)
 | 
			
		||||
                }}>禁用</Button> :
 | 
			
		||||
                <Button theme='light' type='secondary' style={{marginRight: 1}} onClick={async () => {
 | 
			
		||||
                    manageUser(record.username, 'enable', record);
 | 
			
		||||
                }} disabled={record.status === 3}>启用</Button>}
 | 
			
		||||
            <Button theme='light' type='tertiary' style={{marginRight: 1}} onClick={() => {
 | 
			
		||||
                setEditingUser(record);
 | 
			
		||||
                setShowEditUser(true);
 | 
			
		||||
            }}>编辑</Button>
 | 
			
		||||
        </div>),
 | 
			
		||||
    },];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user