fix(mobile): повторный enroll и удаление устройств в UI (0.9.10).
При повторной привязке Seaca переиспользуется запись device_uuid вместо INSERT.
Добавлены POST /devices/{id}/revoke и DELETE для полного удаления записи в настройках SAC.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
{
|
||||
"name": "sac-ui",
|
||||
"private": true,
|
||||
"version": "0.7.4",
|
||||
"version": "0.9.10",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
+6
-2
@@ -1,4 +1,4 @@
|
||||
const TOKEN_KEY = "sac_token";
|
||||
const TOKEN_KEY = "sac_token";
|
||||
const ROLE_KEY = "sac_role";
|
||||
|
||||
export function getToken(): string | null {
|
||||
@@ -373,7 +373,11 @@ export function fetchMobileDevices(): Promise<MobileDevice[]> {
|
||||
}
|
||||
|
||||
export function revokeMobileDevice(deviceId: number): Promise<MobileDevice> {
|
||||
return apiFetch<MobileDevice>(`/api/v1/mobile/devices/${deviceId}`, { method: "DELETE" });
|
||||
return apiFetch<MobileDevice>(`/api/v1/mobile/devices/${deviceId}/revoke`, { method: "POST" });
|
||||
}
|
||||
|
||||
export function deleteMobileDevice(deviceId: number): Promise<void> {
|
||||
return apiFetch<void>(`/api/v1/mobile/devices/${deviceId}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
export function testMobileDevicePush(deviceId: number): Promise<{ message: string }> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
|
||||
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
|
||||
export const APP_NAME = "Security Alert Center";
|
||||
export const APP_VERSION = "0.9.9";
|
||||
export const APP_VERSION = "0.9.10";
|
||||
export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="settings-page">
|
||||
<h1>Настройки</h1>
|
||||
<p class="settings-intro">
|
||||
@@ -190,6 +190,7 @@
|
||||
<tr>
|
||||
<th>Имя</th>
|
||||
<th>Пользователь</th>
|
||||
<th>Статус</th>
|
||||
<th>FCM</th>
|
||||
<th>Последняя активность</th>
|
||||
<th>Действия</th>
|
||||
@@ -199,6 +200,7 @@
|
||||
<tr v-for="device in mobileDevices" :key="device.id">
|
||||
<td>{{ device.display_name }}</td>
|
||||
<td>{{ device.username }}</td>
|
||||
<td>{{ device.is_active ? "активно" : "отключено" }}</td>
|
||||
<td>{{ device.has_fcm_token ? "да" : "нет" }}</td>
|
||||
<td>{{ device.last_seen_at || device.enrolled_at }}</td>
|
||||
<td class="settings-mobile-actions">
|
||||
@@ -219,6 +221,13 @@
|
||||
>
|
||||
Отключить
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="danger"
|
||||
@click="deleteDevice(device.id)"
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -428,6 +437,7 @@ import {
|
||||
fetchMobileSettings,
|
||||
fetchUsers,
|
||||
revokeMobileDevice,
|
||||
deleteMobileDevice,
|
||||
revokeMobileEnrollmentCode,
|
||||
testMobileDevicePush,
|
||||
updateMobileSettings,
|
||||
@@ -781,6 +791,23 @@ async function revokeDevice(deviceId: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteDevice(deviceId: number) {
|
||||
const device = mobileDevices.value.find((item) => item.id === deviceId);
|
||||
const label = device?.display_name || `#${deviceId}`;
|
||||
if (!window.confirm(`Удалить запись устройства «${label}» из базы? Повторная привязка потребует новый код enroll.`)) {
|
||||
return;
|
||||
}
|
||||
error.value = "";
|
||||
success.value = "";
|
||||
try {
|
||||
await deleteMobileDevice(deviceId);
|
||||
mobileDevices.value = await fetchMobileDevices();
|
||||
success.value = "Запись устройства удалена.";
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : "Ошибка";
|
||||
}
|
||||
}
|
||||
|
||||
async function testDevicePush(deviceId: number) {
|
||||
error.value = "";
|
||||
success.value = "";
|
||||
|
||||
Reference in New Issue
Block a user