diff --git a/backend/app/version.py b/backend/app/version.py index 3b96cb9..977bc27 100644 --- a/backend/app/version.py +++ b/backend/app/version.py @@ -1,5 +1,5 @@ """Единый источник версии SAC (API, health, логи, OpenAPI).""" APP_NAME = "Security Alert Center" -APP_VERSION = "0.20.32" +APP_VERSION = "0.20.33" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" diff --git a/backend/tests/test_health.py b/backend/tests/test_health.py index 416dd04..c0e406a 100644 --- a/backend/tests/test_health.py +++ b/backend/tests/test_health.py @@ -4,6 +4,6 @@ from app.version import APP_NAME, APP_VERSION, APP_VERSION_LABEL def test_version_constants(): - assert APP_VERSION == "0.20.32" + assert APP_VERSION == "0.20.33" assert APP_NAME == "Security Alert Center" - assert APP_VERSION_LABEL == "Security Alert Center v.0.20.32" + assert APP_VERSION_LABEL == "Security Alert Center v.0.20.33" diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 18ecc97..efcc304 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1,4 +1,4 @@ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ export const APP_NAME = "Security Alert Center"; -export const APP_VERSION = "0.20.32"; +export const APP_VERSION = "0.20.33"; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`; diff --git a/frontend/src/views/DashboardView.vue b/frontend/src/views/DashboardView.vue index ee6b6d2..8276ce4 100644 --- a/frontend/src/views/DashboardView.vue +++ b/frontend/src/views/DashboardView.vue @@ -297,6 +297,15 @@ > qwinsta + @@ -333,6 +342,7 @@ import { onMounted, onUnmounted, ref } from "vue"; import { apiFetch, getToken, + postEventTerminateSession, type DashboardSummary, type EventSummary, } from "../api"; @@ -342,9 +352,11 @@ import { useRdgQwinsta } from "../composables/useRdgQwinsta"; import { useSacVersion } from "../composables/useSacVersion"; import { formatServerName } from "../utils/hostDisplay"; import { hasRdgFlapUi, rdgFlapQwinstaEventId } from "../utils/rdgFlap"; +import { eventSupportsSessionTerminate } from "../utils/sessionActions"; const { appName, appVersion } = useSacVersion(); const { qwinstaLoadingId, qwinstaModal, closeQwinstaModal, runQwinsta, runLogoff } = useRdgQwinsta(); +const sessionTerminateLoadingId = ref(null); const data = ref(null); @@ -366,6 +378,22 @@ function formatDt(iso: string) { } +async function runSessionTerminate(event: EventSummary) { + const label = event.actor_user || event.title; + if (!window.confirm(`Завершить сессию пользователя ${label}?`)) return; + sessionTerminateLoadingId.value = event.id; + try { + const res = await postEventTerminateSession(event.id); + if (!res.ok) { + window.alert(res.message); + } + } catch (e) { + window.alert(e instanceof Error ? e.message : "Ошибка завершения сессии"); + } finally { + sessionTerminateLoadingId.value = null; + } +} + function syncLastKnownFromRecent() {