fix(mobile): повторный enroll и удаление устройств в UI (0.9.10).

При повторной привязке Seaca переиспользуется запись device_uuid вместо INSERT.
Добавлены POST /devices/{id}/revoke и DELETE для полного удаления записи в настройках SAC.
This commit is contained in:
2026-06-13 16:36:07 +10:00
parent e022f2f213
commit 3d36faa49d
10 changed files with 186 additions and 39 deletions
+79 -2
View File
@@ -1,4 +1,4 @@
"""Mobile / Seaca API."""
"""Mobile / Seaca API."""
from datetime import datetime, timedelta, timezone
@@ -139,7 +139,7 @@ def test_revoke_device_blocks_token(client, db_session, jwt_headers):
data = enroll.json()
headers = {"Authorization": f"Bearer {data['access_token']}"}
revoke = client.delete(f"/api/v1/mobile/devices/{data['device_id']}", headers=jwt_headers)
revoke = client.post(f"/api/v1/mobile/devices/{data['device_id']}/revoke", headers=jwt_headers)
assert revoke.status_code == 200
me = client.put(
@@ -148,3 +148,80 @@ def test_revoke_device_blocks_token(client, db_session, jwt_headers):
json={"fcm_token": "new-token"},
)
assert me.status_code == 401
def test_reenroll_same_device_after_revoke(client, db_session, jwt_headers):
_enable_mobile(db_session)
device_uuid = "uuid-reenroll-001"
first_code = client.post(
"/api/v1/mobile/enrollment-codes",
headers=jwt_headers,
json={"login_mode": "password"},
).json()["enrollment_code"]
first = client.post(
"/api/v1/mobile/enroll",
json={
"enrollment_code": first_code,
"username": "test-monitor",
"password": "test-monitor-password",
"device_uuid": device_uuid,
"display_name": "Phone A",
},
)
assert first.status_code == 200
first_device_id = first.json()["device_id"]
revoke = client.post(f"/api/v1/mobile/devices/{first_device_id}/revoke", headers=jwt_headers)
assert revoke.status_code == 200
second_code = client.post(
"/api/v1/mobile/enrollment-codes",
headers=jwt_headers,
json={"login_mode": "password"},
).json()["enrollment_code"]
second = client.post(
"/api/v1/mobile/enroll",
json={
"enrollment_code": second_code,
"username": "test-monitor",
"password": "test-monitor-password",
"device_uuid": device_uuid,
"display_name": "Phone B",
},
)
assert second.status_code == 200
assert second.json()["device_id"] == first_device_id
devices = client.get("/api/v1/mobile/devices", headers=jwt_headers)
assert devices.status_code == 200
assert len(devices.json()) == 1
assert devices.json()[0]["display_name"] == "Phone B"
assert devices.json()[0]["is_active"] is True
def test_delete_device_record(client, db_session, jwt_headers):
_enable_mobile(db_session)
create = client.post(
"/api/v1/mobile/enrollment-codes",
headers=jwt_headers,
json={"login_mode": "password"},
)
code = create.json()["enrollment_code"]
enroll = client.post(
"/api/v1/mobile/enroll",
json={
"enrollment_code": code,
"username": "test-monitor",
"password": "test-monitor-password",
"device_uuid": "uuid-delete-001",
},
)
device_id = enroll.json()["device_id"]
deleted = client.delete(f"/api/v1/mobile/devices/{device_id}", headers=jwt_headers)
assert deleted.status_code == 204
devices = client.get("/api/v1/mobile/devices", headers=jwt_headers)
assert devices.status_code == 200
assert devices.json() == []