refactor: 移除 Session 架构下已无用的 TokenVersion 即时吊销机制
- 删除 UserRepo.IncrementTokenVersion/FindTokenVersion 方法 - 从 userAuthStore/userAdminStore 接口移除 IncrementTokenVersion - 删除 middleware.tokenVersionStore 接口(中间件不再查询 token_version) - auth_service: DeleteAccount/InvalidateSessions 仅调用 DestroyByUID - admin_service: UpdateUserStatus/ResetUserToken 仅调用 DestroyByUID - FindByIDForAuth/FindByIDUnscoped Select 移除 token_version 列 - 新架构下登出/改密/封禁统一走 sessionManager.DestroyByUID,无需 token_version
This commit is contained in:
@ -1,7 +1,3 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
// tokenVersionStore 最小接口:AuthMiddleware 不再需要此接口(session 替换 JWT)
|
// repository.go: JWT tokenVersionStore 接口已随 Session 迁移移除,保留占位,后续清理。
|
||||||
// 保留占位,待后续清理
|
|
||||||
type tokenVersionStore interface {
|
|
||||||
FindTokenVersion(userID uint) (int, error)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -74,28 +74,11 @@ func (r *UserRepo) ExistsByEmailExclude(email string, excludeUID uint) (bool, er
|
|||||||
return count > 0, err
|
return count > 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementTokenVersion 递增用户令牌版本,使所有已签发的 JWT 即时失效
|
// FindByIDForAuth 认证专用查询:返回 uid/email/username/role/status
|
||||||
func (r *UserRepo) IncrementTokenVersion(userID uint) error {
|
|
||||||
return r.db.Unscoped().Model(&model.User{}).Where("uid = ?", userID).
|
|
||||||
UpdateColumn("token_version", gorm.Expr("token_version + 1")).Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindTokenVersion 按 UID 查询当前令牌版本(轻量查询,仅 SELECT token_version)
|
|
||||||
func (r *UserRepo) FindTokenVersion(userID uint) (int, error) {
|
|
||||||
var version int
|
|
||||||
err := r.db.Model(&model.User{}).
|
|
||||||
Select("token_version").
|
|
||||||
Where("uid = ?", userID).
|
|
||||||
Scan(&version).Error
|
|
||||||
return version, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindByIDForAuth 认证专用查询:返回 uid/email/username/role/status/token_version
|
|
||||||
// 比 FindByID 轻量(不查 avatar、bio 等无用字段),避免全量 SELECT *
|
// 比 FindByID 轻量(不查 avatar、bio 等无用字段),避免全量 SELECT *
|
||||||
// 使用默认 scope(排除软删除),locked 用户不可持有有效 JWT
|
|
||||||
func (r *UserRepo) FindByIDForAuth(userID uint) (*model.User, error) {
|
func (r *UserRepo) FindByIDForAuth(userID uint) (*model.User, error) {
|
||||||
var user model.User
|
var user model.User
|
||||||
err := r.db.Select("uid", "email", "username", "role", "status", "token_version").
|
err := r.db.Select("uid", "email", "username", "role", "status").
|
||||||
First(&user, userID).Error
|
First(&user, userID).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -106,7 +89,7 @@ func (r *UserRepo) FindByIDForAuth(userID uint) (*model.User, error) {
|
|||||||
// FindByIDUnscoped 管理后台专用:含软删除用户,用于解锁/封禁等操作
|
// FindByIDUnscoped 管理后台专用:含软删除用户,用于解锁/封禁等操作
|
||||||
func (r *UserRepo) FindByIDUnscoped(userID uint) (*model.User, error) {
|
func (r *UserRepo) FindByIDUnscoped(userID uint) (*model.User, error) {
|
||||||
var user model.User
|
var user model.User
|
||||||
err := r.db.Unscoped().Select("uid", "email", "username", "role", "status", "token_version", "deleted_at").
|
err := r.db.Unscoped().Select("uid", "email", "username", "role", "status", "deleted_at").
|
||||||
First(&user, userID).Error
|
First(&user, userID).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -95,21 +95,15 @@ func (s *AdminService) UpdateUserStatus(operatorUID, targetUID uint, newStatus s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 修改状态必须立刻让已有 session 失效 + 递增 token_version(向后兼容)
|
// 修改状态必须立刻让已有 session 失效
|
||||||
if err := s.sessionManager.DestroyByUID(target.ID); err != nil {
|
return s.sessionManager.DestroyByUID(target.ID)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.userRepo.IncrementTokenVersion(target.ID)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetUserToken 强制下线:销毁所有 session + 递增 token_version
|
// ResetUserToken 强制下线:销毁所有 session
|
||||||
func (s *AdminService) ResetUserToken(operatorUID, targetUID uint) error {
|
func (s *AdminService) ResetUserToken(operatorUID, targetUID uint) error {
|
||||||
return s.checkAndOperate(operatorUID, targetUID, func(_ *model.User, target *model.User) error {
|
return s.checkAndOperate(operatorUID, targetUID, func(_ *model.User, target *model.User) error {
|
||||||
if err := s.sessionManager.DestroyByUID(target.ID); err != nil {
|
return s.sessionManager.DestroyByUID(target.ID)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.userRepo.IncrementTokenVersion(target.ID)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -259,11 +259,7 @@ func (s *AuthService) DeleteAccount(userID uint, password, reason string) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除所有 session + 递增 token_version(向后兼容)
|
return s.invalidateSessions(userID)
|
||||||
if err := s.invalidateSessions(userID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.userRepo.IncrementTokenVersion(userID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalidateSessions 销毁某用户的所有 session(内部方法)
|
// invalidateSessions 销毁某用户的所有 session(内部方法)
|
||||||
@ -273,10 +269,7 @@ func (s *AuthService) invalidateSessions(userID uint) error {
|
|||||||
|
|
||||||
// InvalidateSessions 公开方法:销毁用户所有 session(供 admin 等外部调用)
|
// InvalidateSessions 公开方法:销毁用户所有 session(供 admin 等外部调用)
|
||||||
func (s *AuthService) InvalidateSessions(userID uint) error {
|
func (s *AuthService) InvalidateSessions(userID uint) error {
|
||||||
if err := s.invalidateSessions(userID); err != nil {
|
return s.sessionManager.DestroyByUID(userID)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.userRepo.IncrementTokenVersion(userID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateProfile 修改个人资料
|
// UpdateProfile 修改个人资料
|
||||||
|
|||||||
@ -2,14 +2,13 @@ package service
|
|||||||
|
|
||||||
import "metazone.cc/metalab/internal/model"
|
import "metazone.cc/metalab/internal/model"
|
||||||
|
|
||||||
// userAuthStore AuthService 所需的最小仓储接口(ISP:8 个方法)
|
// userAuthStore AuthService 所需的最小仓储接口(ISP:7 个方法)
|
||||||
type userAuthStore interface {
|
type userAuthStore interface {
|
||||||
ExistsByEmail(email string) (bool, error)
|
ExistsByEmail(email string) (bool, error)
|
||||||
Create(user *model.User) error
|
Create(user *model.User) error
|
||||||
FindByEmail(email string) (*model.User, error)
|
FindByEmail(email string) (*model.User, error)
|
||||||
FindByID(id uint) (*model.User, error)
|
FindByID(id uint) (*model.User, error)
|
||||||
Update(user *model.User) error
|
Update(user *model.User) error
|
||||||
IncrementTokenVersion(userID uint) error
|
|
||||||
ExistsByUsername(username string) (bool, error)
|
ExistsByUsername(username string) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ type userTokenStore interface {
|
|||||||
FindByIDForAuth(userID uint) (*model.User, error)
|
FindByIDForAuth(userID uint) (*model.User, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// userAdminStore AdminService 所需的最小仓储接口
|
// userAdminStore AdminService 所需的最小仓储接口(ISP:7 个方法)
|
||||||
type userAdminStore interface {
|
type userAdminStore interface {
|
||||||
CountSearchUsers(keyword, role, status string) (int64, error)
|
CountSearchUsers(keyword, role, status string) (int64, error)
|
||||||
SearchUsers(keyword, role, status string, offset, limit int) ([]model.User, error)
|
SearchUsers(keyword, role, status string, offset, limit int) ([]model.User, error)
|
||||||
@ -27,7 +26,6 @@ type userAdminStore interface {
|
|||||||
SoftDelete(uid uint) error
|
SoftDelete(uid uint) error
|
||||||
Restore(uid uint) error
|
Restore(uid uint) error
|
||||||
ExistsByEmailExclude(email string, excludeUID uint) (bool, error)
|
ExistsByEmailExclude(email string, excludeUID uint) (bool, error)
|
||||||
IncrementTokenVersion(userID uint) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// postStore PostService 所需的最小仓储接口
|
// postStore PostService 所需的最小仓储接口
|
||||||
|
|||||||
Reference in New Issue
Block a user