feat: 登录设备管理与编辑器图片上传
- 新增登录设备列表与会话下线(ListLoginDevices/RevokeLoginDevice),按设备指纹识别当前会话 - Markdown 编辑器新增图片插入弹窗与图片上传(ImageInsertModal) - 实时总线、账号守卫与用户事件适配
This commit is contained in:
@@ -191,27 +191,30 @@ func (s *AuthService) TouchDeviceFromRefresh(plain, ip, ua string, userID uint)
|
||||
return fid
|
||||
}
|
||||
|
||||
func (s *AuthService) revokeSameFingerprintExcept(userID, keepFamily uint, ip, ua string) {
|
||||
fp := deviceFingerprint(ip, ua)
|
||||
// revokeAllSessionsExcept 真·单会话:登录时吊销该用户除新会话外的全部
|
||||
// 有效会话(任何新登录都踢掉所有旧设备);返回吊销行数供上层广播告知。
|
||||
func (s *AuthService) revokeAllSessionsExcept(userID, keepFamily uint) int {
|
||||
now := time.Now()
|
||||
var actives []model.RefreshToken
|
||||
if err := s.db.Select("id", "family_id", "ip", "user_agent").
|
||||
if err := s.db.Select("id", "family_id").
|
||||
Where("user_id = ? AND revoked = ? AND expires_at > ?", userID, false, now).
|
||||
Find(&actives).Error; err != nil {
|
||||
return
|
||||
return 0
|
||||
}
|
||||
ids := make([]uint, 0)
|
||||
for _, t := range actives {
|
||||
if sessionFamilyID(t) == keepFamily {
|
||||
continue
|
||||
}
|
||||
if deviceFingerprint(t.IP, t.UserAgent) == fp {
|
||||
ids = append(ids, t.ID)
|
||||
}
|
||||
ids = append(ids, t.ID)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
return 0
|
||||
}
|
||||
s.db.Model(&model.RefreshToken{}).Where("id IN ?", ids).
|
||||
res := s.db.Model(&model.RefreshToken{}).Where("id IN ?", ids).
|
||||
Updates(map[string]any{"revoked": true, "token_cipher": "", "updated_at": now})
|
||||
if res.Error != nil {
|
||||
return 0
|
||||
}
|
||||
return int(res.RowsAffected)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user