Skip to content

Commit a9c832c

Browse files
author
Chang lue Tsen
committed
feat(user): implement soft deletion for user accounts and update related logic
1 parent e027cbb commit a9c832c

6 files changed

Lines changed: 42 additions & 45 deletions

File tree

apis/types.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ type (
3232
CreatedAt int64 `json:"created_at"`
3333
UpdatedAt int64 `json:"updated_at"`
3434
DeletedAt int64 `json:"deleted_at,omitempty"`
35-
IsDel bool `json:"is_del,omitempty"`
3635
}
3736
Follow {
3837
Id int64 `json:"id"`

internal/logic/auth/userLoginLogic.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
6868

6969
userInfo, err = l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email)
7070

71+
if userInfo.DeletedAt.Valid {
72+
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserNotExist), "user email deleted: %v", req.Email)
73+
}
74+
7175
if err != nil {
7276
if errors.As(err, &gorm.ErrRecordNotFound) {
7377
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserNotExist), "user email not exist: %v", req.Email)

internal/logic/auth/userRegisterLogic.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,16 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
7979
}
8080
}
8181
// Check if the user exists
82-
_, err = l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email)
82+
u, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email)
8383
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
8484
l.Errorw("FindOneByEmail Error", logger.Field("error", err))
8585
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user info failed: %v", err.Error())
86-
} else if err == nil {
86+
} else if err == nil && !u.DeletedAt.Valid {
8787
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserExist), "user email exist: %v", req.Email)
88+
} else if err == nil && u.DeletedAt.Valid {
89+
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserDisabled), "user email deleted: %v", req.Email)
8890
}
91+
8992
// Generate password
9093
pwd := tool.EncodePassWord(req.Password)
9194
userInfo := &user.User{

internal/model/user/default.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77

88
"github.com/perfect-panel/server/pkg/cache"
9+
"github.com/perfect-panel/server/pkg/logger"
910
"github.com/redis/go-redis/v9"
1011
"gorm.io/gorm"
1112
)
@@ -72,7 +73,7 @@ func (m *defaultUserModel) FindOneByEmail(ctx context.Context, email string) (*U
7273
if err := conn.Model(&AuthMethods{}).Where("`auth_type` = 'email' AND `auth_identifier` = ?", email).First(&data).Error; err != nil {
7374
return err
7475
}
75-
return conn.Model(&User{}).Where("`id` = ?", data.UserId).Preload("UserDevices").Preload("AuthMethods").First(v).Error
76+
return conn.Model(&User{}).Unscoped().Where("`id` = ?", data.UserId).Preload("UserDevices").Preload("AuthMethods").First(v).Error
7677
})
7778
return &user, err
7879
}
@@ -91,7 +92,7 @@ func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error)
9192
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
9293
var resp User
9394
err := m.QueryCtx(ctx, &resp, userIdKey, func(conn *gorm.DB, v interface{}) error {
94-
return conn.Model(&User{}).Where("`id` = ?", id).Preload("UserDevices").Preload("AuthMethods").First(&resp).Error
95+
return conn.Model(&User{}).Unscoped().Where("`id` = ?", id).Preload("UserDevices").Preload("AuthMethods").First(&resp).Error
9596
})
9697
return &resp, err
9798
}
@@ -119,35 +120,23 @@ func (m *defaultUserModel) Delete(ctx context.Context, id int64, tx ...*gorm.DB)
119120
return err
120121
}
121122

122-
// 使用批量相关缓存清理,包含所有相关数据的缓存
123+
// Use batch related cache cleaning, including a cache of all relevant data
123124
defer func() {
124125
if clearErr := m.BatchClearRelatedCache(ctx, data); clearErr != nil {
125-
// 记录清理缓存错误,但不阻断删除操作
126+
// Record cache cleaning errors, but do not block deletion operations
127+
logger.Errorf("failed to clear related cache for user %d: %v", id, clearErr.Error())
126128
}
127129
}()
128130

129131
return m.TransactCtx(ctx, func(db *gorm.DB) error {
130132
if len(tx) > 0 {
131133
db = tx[0]
132134
}
133-
134-
// 删除用户相关的所有数据
135+
// Soft deletion of user information without any processing of other information (Determine whether to allow login/subscription based on the user's deletion status)
135136
if err := db.Model(&User{}).Where("`id` = ?", id).Delete(&User{}).Error; err != nil {
136137
return err
137138
}
138139

139-
if err := db.Model(&AuthMethods{}).Where("`user_id` = ?", id).Delete(&AuthMethods{}).Error; err != nil {
140-
return err
141-
}
142-
143-
if err := db.Model(&Subscribe{}).Where("`user_id` = ?", id).Delete(&Subscribe{}).Error; err != nil {
144-
return err
145-
}
146-
147-
if err := db.Model(&Device{}).Where("`user_id` = ?", id).Delete(&Device{}).Error; err != nil {
148-
return err
149-
}
150-
151140
return nil
152141
})
153142
}

internal/model/user/user.go

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,35 @@ package user
22

33
import (
44
"time"
5+
6+
"gorm.io/gorm"
57
)
68

79
type User struct {
8-
Id int64 `gorm:"primaryKey"`
9-
Password string `gorm:"type:varchar(100);not null;comment:User Password"`
10-
Algo string `gorm:"type:varchar(20);default:'default';comment:Encryption Algorithm"`
11-
Salt string `gorm:"type:varchar(20);default:null;comment:Password Salt"`
12-
Avatar string `gorm:"type:MEDIUMTEXT;comment:User Avatar"`
13-
Balance int64 `gorm:"default:0;comment:User Balance"` // User Balance Amount
14-
ReferCode string `gorm:"type:varchar(20);default:'';comment:Referral Code"`
15-
RefererId int64 `gorm:"index:idx_referer;comment:Referrer ID"`
16-
Commission int64 `gorm:"default:0;comment:Commission"` // Commission Amount
17-
ReferralPercentage uint8 `gorm:"default:0;comment:Referral"` // Referral Percentage
18-
OnlyFirstPurchase *bool `gorm:"default:true;not null;comment:Only First Purchase"` // Only First Purchase Referral
19-
GiftAmount int64 `gorm:"default:0;comment:User Gift Amount"`
20-
Enable *bool `gorm:"default:true;not null;comment:Is Account Enabled"`
21-
IsAdmin *bool `gorm:"default:false;not null;comment:Is Admin"`
22-
EnableBalanceNotify *bool `gorm:"default:false;not null;comment:Enable Balance Change Notifications"`
23-
EnableLoginNotify *bool `gorm:"default:false;not null;comment:Enable Login Notifications"`
24-
EnableSubscribeNotify *bool `gorm:"default:false;not null;comment:Enable Subscription Notifications"`
25-
EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"`
26-
AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"`
27-
UserDevices []Device `gorm:"foreignKey:UserId;references:Id"`
28-
Rules string `gorm:"type:TEXT;comment:User Rules"`
29-
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
30-
UpdatedAt time.Time `gorm:"comment:Update Time"`
10+
Id int64 `gorm:"primaryKey"`
11+
Password string `gorm:"type:varchar(100);not null;comment:User Password"`
12+
Algo string `gorm:"type:varchar(20);default:'default';comment:Encryption Algorithm"`
13+
Salt string `gorm:"type:varchar(20);default:null;comment:Password Salt"`
14+
Avatar string `gorm:"type:MEDIUMTEXT;comment:User Avatar"`
15+
Balance int64 `gorm:"default:0;comment:User Balance"` // User Balance Amount
16+
ReferCode string `gorm:"type:varchar(20);default:'';comment:Referral Code"`
17+
RefererId int64 `gorm:"index:idx_referer;comment:Referrer ID"`
18+
Commission int64 `gorm:"default:0;comment:Commission"` // Commission Amount
19+
ReferralPercentage uint8 `gorm:"default:0;comment:Referral"` // Referral Percentage
20+
OnlyFirstPurchase *bool `gorm:"default:true;not null;comment:Only First Purchase"` // Only First Purchase Referral
21+
GiftAmount int64 `gorm:"default:0;comment:User Gift Amount"`
22+
Enable *bool `gorm:"default:true;not null;comment:Is Account Enabled"`
23+
IsAdmin *bool `gorm:"default:false;not null;comment:Is Admin"`
24+
EnableBalanceNotify *bool `gorm:"default:false;not null;comment:Enable Balance Change Notifications"`
25+
EnableLoginNotify *bool `gorm:"default:false;not null;comment:Enable Login Notifications"`
26+
EnableSubscribeNotify *bool `gorm:"default:false;not null;comment:Enable Subscription Notifications"`
27+
EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"`
28+
AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"`
29+
UserDevices []Device `gorm:"foreignKey:UserId;references:Id"`
30+
Rules string `gorm:"type:TEXT;comment:User Rules"`
31+
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
32+
UpdatedAt time.Time `gorm:"comment:Update Time"`
33+
DeletedAt gorm.DeletedAt `gorm:"index;comment:Deletion Time"`
3134
}
3235

3336
func (*User) TableName() string {

internal/types/types.go

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)