fix(admin): достроить вторые половины отзыва доступа, лимита и журнала
Разбор кода на c0a43ae со сверкой с официальной документацией Hysteria 2.
Общая тема: операции, у которых была только одна из двух необходимых половин.
Отзыв доступа. Запись disabled=1 видит лишь выборка в Hysteria2Auth, то есть
закрывает БУДУЩИЕ обращения к HTTP-auth; установленная QUIC-сессия живёт своей
жизнью и сама не разрывается. После «Отключить» пир пользовался доступом сколько
угодно долго, а панель показывала его отключённым. Появился DisconnectPeers —
только официальный Traffic Stats /kick, без записи в базу; прежний Hysteria2Kick
вместе с разрывом проставлял banned_until и потому для отключения не годился.
Порядок «запись, затем разрыв» обратному не подлежит и доказан снимком базы в
момент прихода /kick. Неудача разрыва не откатывает disabled и сообщается кодом
peer_disconnect_failed: обычная ошибка означала бы для оператора вывод, прямо
противоположный истине. KickPeer переведён на тот же примитив — он писал
banned_until дважды и мог ответить чистым отказом уже в применённом состоянии.
Ограничение устройств. Отказ /online обрабатывался возвратом успеха
авторизации, то есть недоступность 127.0.0.1 превращала объявленный лимит в
безлимит. Вторая половина дыры была тише: Hysteria2Online отдавал пустую карту
БЕЗ ошибки, когда systemd отвечал «служба неактивна», — а этот ответ не
отличается от «спросить systemctl не удалось». Пути разделены: терпимый для
отображения, строгий для решения о доступе. Hysteria2IsRunning убран с путей
принятия решений совсем.
Журнал. entry.Info() вызывался без аргумента, и logrus писал "msg":"" для
каждого запроса — пустой столбец на экране был точным отражением файла. Ветка
«файла ещё нет» отвечала голым массивом вместо {records,total}, поэтому на
свежей установке страница системных логов не работала вовсе. Битая строка
вызывала vo.Fail И continue: клиент получал два JSON-документа подряд.
Панель. Общий LogViewer и utils/download.ts (копий скачивания было четыре, две
ставили запрос вне try и глушили причину); меню на command с быстрым
включением/отключением; popper-style у подсказки; kick с подтверждением и
названным сроком; отмена подтверждений перестала быть ошибкой. Отдельно:
skipErrorToast гасил и транспортный отказ, при том что страницы писали
«перехватчик уже показал» и молчали, — обрыв связи не показывал ничего.
Закреплено go-тестами против настоящего HTTP, контрактными тестами панели и
двумя гейтами приёмки. Ручная часть — в
docs/acceptance/2026-09-01-v1.0.0-rc2-preflight-findings.md.
This commit is contained in:
@@ -21,7 +21,13 @@ const t = i18n.global.t;
|
||||
* Запрос может отказаться от общего тоста, если показывает причину сам.
|
||||
*
|
||||
* Так делает форма пира: причины по полям она подставляет прямо под поля, и
|
||||
* второй сигнал тостом там только шумит.
|
||||
* второй сигнал тостом там только шумит. Так же поступают действия над строкой
|
||||
* пира: отзыв доступа умеет завершиться частично, и такой исход показывается
|
||||
* предупреждением, а не ошибкой.
|
||||
*
|
||||
* Флаг относится ТОЛЬКО к отказу API — тому, у которого есть конверт с `code`
|
||||
* и `errors`. Транспортный отказ показывается всегда: разбирать в нём нечего,
|
||||
* и молчание о нём означало бы операцию, не происходящую без объяснений.
|
||||
*/
|
||||
declare module "axios" {
|
||||
export interface AxiosRequestConfig {
|
||||
@@ -138,9 +144,21 @@ service.interceptors.response.use(
|
||||
? t("common.systemError")
|
||||
: t("common.networkError");
|
||||
|
||||
if (!error.config?.skipErrorToast) {
|
||||
ElMessage.error(message);
|
||||
}
|
||||
// skipErrorToast здесь НЕ действует, и это существенно.
|
||||
//
|
||||
// Флаг существует ради одного случая: страница разбирает причину отказа
|
||||
// сама — раскладывает её по полям формы или отличает частичный результат
|
||||
// от полного отказа по коду. Всё это возможно только для отказа API, у
|
||||
// которого есть конверт с `code` и `errors`.
|
||||
//
|
||||
// У транспортного отказа конверта нет вовсе. Страница о нём не может
|
||||
// сказать ничего, кроме того же «сервер не отвечает», и все они пишут в
|
||||
// своих обработчиках `// транспортный отказ уже показан общим
|
||||
// перехватчиком» и молчат. Пока флаг гасил и эту ветку, утверждение было
|
||||
// ложным: обрыв соединения при сохранении пира, его удалении или отзыве
|
||||
// доступа не показывал оператору НИЧЕГО — операция просто не происходила
|
||||
// молча.
|
||||
ElMessage.error(message);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user