Ausgegebene Medien löschen, Gerät löschen deprovisioniert zusätzlich
DELETE /api/v1/organizations/<org>/enrollment-sessions/<id> entfernt nur nicht mehr nutzbare Medien (widerrufen, abgelaufen, aufgebraucht). archive_device() entzieht jetzt auch das Agent-Secret: ein gelöschtes Gerät checkte bisher weiter ein (Liebherr-47, 03.10.2026). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5284bb470b
commit
2f6dfd585b
1 file changed
+61
-1
@@ -3830,6 +3830,11 @@ def archive_device(device_id: str) -> bool:
|
||||
aus fetch_devices_for_organization()/fetch_all_devices(), Datensatz und
|
||||
Historie (hardware_snapshots, device_merkmal_events) bleiben in der DB
|
||||
erhalten.
|
||||
|
||||
Seit 23.10.2026 zugleich deprovisioniert (wie deprovision_device()):
|
||||
Vorher checkte ein gelöschtes Gerät weiter ein und wurde unsichtbar
|
||||
weiterverwaltet (Liebherr-47, gelöscht 03.10. 13:56, Check-in 16:24).
|
||||
Eine Neuinstallation (/api/v1/activate) setzt beides wieder zurück.
|
||||
"""
|
||||
|
||||
with get_database_connection() as conn:
|
||||
@@ -3837,7 +3842,9 @@ def archive_device(device_id: str) -> bool:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE devices
|
||||
SET archived_at = CURRENT_TIMESTAMP
|
||||
SET archived_at = CURRENT_TIMESTAMP,
|
||||
deprovisioned_at = COALESCE(deprovisioned_at, CURRENT_TIMESTAMP),
|
||||
agent_secret_hash = NULL, agent_secret_issued_at = NULL
|
||||
WHERE id = %s AND archived_at IS NULL
|
||||
RETURNING id
|
||||
""",
|
||||
@@ -5736,6 +5743,35 @@ def revoke_enrollment_session(session_id: str):
|
||||
)
|
||||
return cur.fetchone() is not None
|
||||
|
||||
def delete_enrollment_session(organization_id: str, session_id: str) -> str:
|
||||
"""
|
||||
GUI-Runde 23.10.2026: "Ausgegebene Medien" verwalten. Gelöscht wird nur,
|
||||
was ohnehin nicht mehr installieren kann (widerrufen, abgelaufen oder
|
||||
Kontingent aufgebraucht) - ein noch gültiges Medium muss erst
|
||||
deaktiviert werden. Nichts verweist per Fremdschlüssel auf die Session;
|
||||
installierte Geräte bleiben unberührt. Rückgabe: "geloescht",
|
||||
"nicht_gefunden" oder "noch_gueltig".
|
||||
"""
|
||||
|
||||
with get_database_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
DELETE FROM enrollment_sessions
|
||||
WHERE id = %s AND organization_id = %s
|
||||
AND (revoked_at IS NOT NULL OR expires_at <= CURRENT_TIMESTAMP OR devices_used >= max_devices)
|
||||
RETURNING id
|
||||
""",
|
||||
(session_id, organization_id),
|
||||
)
|
||||
if cur.fetchone() is not None:
|
||||
return "geloescht"
|
||||
cur.execute(
|
||||
"SELECT 1 FROM enrollment_sessions WHERE id = %s AND organization_id = %s",
|
||||
(session_id, organization_id),
|
||||
)
|
||||
return "noch_gueltig" if cur.fetchone() is not None else "nicht_gefunden"
|
||||
|
||||
def recharge_enrollment_session(session_id: str, additional_devices: int, expires_at: str | None):
|
||||
"""
|
||||
Phase 5 (Kundenplattform-Selfservice): eine bereits ausgeteilte,
|
||||
@@ -8829,6 +8865,30 @@ def revoke_enrollment_session_endpoint(session_id: str, authorization: str | Non
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@app.delete("/api/v1/organizations/{organization_id}/enrollment-sessions/{session_id}")
|
||||
def delete_enrollment_session_endpoint(
|
||||
organization_id: str, session_id: str, authorization: str | None = Header(default=None)
|
||||
):
|
||||
if not require_service_token(authorization):
|
||||
return {"success": False, "error": "unauthorized", "message": "Fehlendes oder ungültiges Service-Token."}
|
||||
|
||||
try:
|
||||
UUID(session_id)
|
||||
except ValueError:
|
||||
return {"success": False, "error": "not_found", "message": "Installationsmedium wurde nicht gefunden."}
|
||||
|
||||
ergebnis = delete_enrollment_session(organization_id, session_id)
|
||||
if ergebnis == "nicht_gefunden":
|
||||
return {"success": False, "error": "not_found", "message": "Installationsmedium wurde nicht gefunden."}
|
||||
if ergebnis == "noch_gueltig":
|
||||
return {
|
||||
"success": False, "error": "noch_gueltig",
|
||||
"message": "Das Medium ist noch gültig. Deaktiviere es zuerst, dann kannst du es löschen.",
|
||||
}
|
||||
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@app.patch("/api/v1/enrollment-sessions/{session_id}")
|
||||
def recharge_enrollment_session_endpoint(
|
||||
session_id: str,
|
||||
|
||||
Reference in new issue
Block a user