fix(gateway): смена пароля не закрывает сессию текущего устройства
ChangePassword отзывает остальные сессии, но обработчик закрывал соединения всех устройств пользователя — включая то, с которого пароль сменили: страница теряла шлюз в момент успешного ответа, и подтверждение «Пароль изменён» не показывалось (пункт 12 матрицы 11.6, меняли пароль через интерфейс). Добавлен InvalidateUserExcept: текущее соединение опознаётся по хэшу токена сессии, который теперь хранит и буфер RESUME. Для logout-all, бана и админского сброса поведение прежнее — закрываются все соединения. Тест: TestInvalidateUserExceptKeepsCurrentSession (второе устройство получает INVALID_SESSION, текущее продолжает отвечать на heartbeat).
This commit is contained in:
@@ -396,12 +396,29 @@ func (s *Service) SendToUser(userID uint64, event string, payload any) {
|
||||
// (logout-all, смена пароля, действия администратора) — иначе второе
|
||||
// устройство остаётся «в приложении» до следующего запроса (AGENT.md 11.6).
|
||||
func (s *Service) InvalidateUser(userID uint64, reason string) {
|
||||
s.invalidateUser(userID, "", reason)
|
||||
}
|
||||
|
||||
// InvalidateUserExcept закрывает соединения пользователя, кроме текущего:
|
||||
// смена пароля отзывает остальные сессии, но устройство, с которого её
|
||||
// сменили, продолжает работать (AGENT.md 7.1, 11.6).
|
||||
func (s *Service) InvalidateUserExcept(userID uint64, keepTokenHash, reason string) {
|
||||
s.invalidateUser(userID, keepTokenHash, reason)
|
||||
}
|
||||
|
||||
func (s *Service) invalidateUser(userID uint64, keepTokenHash, reason string) {
|
||||
s.mu.Lock()
|
||||
targets := make([]*clientSession, 0, 2)
|
||||
for _, session := range s.sessions {
|
||||
if session.userID == userID {
|
||||
targets = append(targets, session)
|
||||
if session.userID != userID {
|
||||
continue
|
||||
}
|
||||
// Соединение опознаём по хэшу токена сессии: у каждой сессии свой буфер
|
||||
// RESUME, он же хранит владельца (AGENT.md 8.3).
|
||||
if keepTokenHash != "" && session.buffer != nil && session.buffer.tokenHash == keepTokenHash {
|
||||
continue
|
||||
}
|
||||
targets = append(targets, session)
|
||||
}
|
||||
s.mu.Unlock()
|
||||
for _, session := range targets {
|
||||
|
||||
Reference in New Issue
Block a user