diff --git a/internal/api/delete_user.go b/internal/api/delete_user.go index 81c87103f..ccc3be175 100644 --- a/internal/api/delete_user.go +++ b/internal/api/delete_user.go @@ -18,6 +18,7 @@ import ( // It follows the same direct-DB pattern as UserGlobalBlackApi. type DeleteUserApi struct { userDB database.User + phoneSNDB database.PhoneSN authClient *rpcli.AuthClient groupClient group.GroupClient friendClient relation.FriendClient @@ -26,6 +27,7 @@ type DeleteUserApi struct { func NewDeleteUserApi( userDB database.User, + phoneSNDB database.PhoneSN, authClient *rpcli.AuthClient, groupClient group.GroupClient, friendClient relation.FriendClient, @@ -33,6 +35,7 @@ func NewDeleteUserApi( ) *DeleteUserApi { return &DeleteUserApi{ userDB: userDB, + phoneSNDB: phoneSNDB, authClient: authClient, groupClient: groupClient, friendClient: friendClient, @@ -131,7 +134,14 @@ func (d *DeleteUserApi) DeleteUser(c *gin.Context) { pageNumber++ } - // 5. Hard-delete user document from MongoDB. + // 5. Delete phone_sn_info record bound to this user's phone number. + if phone := users[0].Phone; phone != "" { + if err := d.phoneSNDB.DeleteByPhone(c, phone); err != nil { + log.ZWarn(c, "DeleteUser: DeleteByPhone failed", err, "userID", req.UserID, "phone", phone) + } + } + + // 6. Hard-delete user document from MongoDB. // Redis cache will become stale and expire via TTL; the user can no longer // authenticate because their tokens were already invalidated in step 2. if err := d.userDB.Delete(c, []string{req.UserID}); err != nil { diff --git a/internal/api/router.go b/internal/api/router.go index bbfed0eba..9f622be9e 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -137,7 +137,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), config.Share.IMAdminUserID) cp := NewCaptchaApi(pbcaptcha.NewCaptchaClient(captchaConn)) bl := NewUserGlobalBlackApi(blacklistCtrl, userDB, config.Share.IMAdminUserID, rpcli.NewAuthClient(authConn)) - du := NewDeleteUserApi(userDB, rpcli.NewAuthClient(authConn), group.NewGroupClient(groupConn), relation.NewFriendClient(friendConn), config.Share.IMAdminUserID) + du := NewDeleteUserApi(userDB, phoneSNDB, rpcli.NewAuthClient(authConn), group.NewGroupClient(groupConn), relation.NewFriendClient(friendConn), config.Share.IMAdminUserID) phoneSN := NewPhoneSNApi(phoneSNDB) userRouterGroup := r.Group("/user") { diff --git a/pkg/common/storage/database/mgo/phone_sn.go b/pkg/common/storage/database/mgo/phone_sn.go index fa09f3657..594ea72dc 100644 --- a/pkg/common/storage/database/mgo/phone_sn.go +++ b/pkg/common/storage/database/mgo/phone_sn.go @@ -48,6 +48,14 @@ func (p *phoneSNMgo) GetByPhone(ctx context.Context, phone string) (*model.Phone return doc, nil } +func (p *phoneSNMgo) DeleteByPhone(ctx context.Context, phone string) error { + if phone == "" { + return nil + } + _, err := p.coll.DeleteOne(ctx, bson.M{"phone": phone}) + return errs.Wrap(err) +} + func (p *phoneSNMgo) Upsert(ctx context.Context, phone string, userID int64, isSnd bool) error { if phone == "" { return errs.ErrArgs.WrapMsg("phone is empty") diff --git a/pkg/common/storage/database/phone_sn.go b/pkg/common/storage/database/phone_sn.go index 3ded66b0f..055a6c5b5 100644 --- a/pkg/common/storage/database/phone_sn.go +++ b/pkg/common/storage/database/phone_sn.go @@ -17,4 +17,6 @@ type PhoneSN interface { GetByPhone(ctx context.Context, phone string) (*model.PhoneSNInfo, error) // Upsert 写入或更新 is_snd 与 user_id Upsert(ctx context.Context, phone string, userID int64, isSnd bool) error + // DeleteByPhone 按手机号删除记录;记录不存在时不报错 + DeleteByPhone(ctx context.Context, phone string) error }