Skip to content

Commit e644d13

Browse files
solarhelldreamhunter2333
authored andcommitted
fix: 删除用户后无法重新注册同名用户 (#317)
* fix: 删除用户后无法重新注册同名用户 用户删除改为硬删除,解决软删除导致 username 唯一约束冲突的问题。 用户表无业务数据关联,无需保留已删除记录。 同时添加迁移清理历史软删除用户数据。 * fix: Delete 方法在未匹配到行时返回 ErrNotFound * fix: v5 迁移 Down 函数返回不可逆错误,避免误导回滚成功 * fix: UserRepository.Delete 使用 Unscoped 执行硬删除 软删除仅设置 deleted_at 而不移除行,导致 username 唯一约束冲突, 删除用户后无法重新注册同名用户。添加 Unscoped() 确保物理删除。
1 parent 5025113 commit e644d13

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

internal/repository/sqlite/migrations.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,23 @@ var migrations = []Migration{
166166
return nil
167167
},
168168
},
169+
{
170+
Version: 5,
171+
Description: "Hard-delete soft-deleted users to free username unique constraint",
172+
Up: func(db *gorm.DB) error {
173+
result := db.Exec("DELETE FROM users WHERE deleted_at != 0")
174+
if result.Error != nil {
175+
return result.Error
176+
}
177+
if result.RowsAffected > 0 {
178+
log.Printf("[Migration] Purged %d soft-deleted users", result.RowsAffected)
179+
}
180+
return nil
181+
},
182+
Down: func(db *gorm.DB) error {
183+
return errors.New("migration v5 is irreversible: hard-deleted users cannot be restored")
184+
},
185+
},
169186
}
170187

171188
func isMySQLDuplicateIndexError(err error) bool {

internal/repository/sqlite/user.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,16 @@ func (r *UserRepository) Update(u *domain.User) error {
3535
return r.db.gorm.Save(model).Error
3636
}
3737

38+
// Delete 硬删除用户。用户表无业务数据关联,软删除会导致 username 唯一约束冲突,无法重新注册同名用户。
3839
func (r *UserRepository) Delete(tenantID uint64, id uint64) error {
39-
now := time.Now().UnixMilli()
40-
return r.db.gorm.Model(&User{}).
41-
Where("id = ? AND tenant_id = ?", id, tenantID).
42-
Updates(map[string]any{
43-
"deleted_at": now,
44-
"updated_at": now,
45-
}).Error
40+
result := r.db.gorm.Unscoped().Where("id = ? AND tenant_id = ?", id, tenantID).Delete(&User{})
41+
if result.Error != nil {
42+
return result.Error
43+
}
44+
if result.RowsAffected == 0 {
45+
return domain.ErrNotFound
46+
}
47+
return nil
4648
}
4749

4850
func (r *UserRepository) GetByID(tenantID uint64, id uint64) (*domain.User, error) {

0 commit comments

Comments
 (0)