feat: organisationsübergreifende Geräteliste (Kundenplattform-Admin)

Neuer Endpoint GET /api/v1/devices (alle Geräte, Organisationsname
gejoint) für den Admin-Bereich "Verwaltung -> Geräte".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Stallinger 2026-08-05 09:12:20 +02:00
parent e043233aea
commit d7956bf8f7

47
app.py
View File

@ -603,6 +603,41 @@ def fetch_devices_for_organization(organization_id: str):
for device_id, hostname, fingerprint, last_checkin in cur.fetchall() for device_id, hostname, fingerprint, last_checkin in cur.fetchall()
] ]
def fetch_all_devices():
"""
Organisationsübergreifende Geräteliste für den Kundenplattform-Admin-
Bereich (Verwaltung -> Geräte) - Pendant zu fetch_devices_for_organization,
ohne Org-Filter, mit Organisationsname gejoint.
"""
with get_database_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"""
SELECT d.id, d.hostname, d.device_fingerprint, d.agent_last_checkin,
d.organization_id, o.name
FROM devices d
JOIN organizations o ON o.id = d.organization_id
ORDER BY o.name, d.hostname NULLS LAST, d.created_at
"""
)
return [
{
"id": str(device_id),
"hostname": hostname,
"device_fingerprint": fingerprint,
"agent_last_checkin": (
last_checkin.isoformat() if last_checkin is not None else None
),
"organization_id": str(organization_id),
"organization_name": organization_name,
}
for (
device_id, hostname, fingerprint, last_checkin,
organization_id, organization_name,
) in cur.fetchall()
]
def fetch_organizations(): def fetch_organizations():
with get_database_connection() as conn: with get_database_connection() as conn:
with conn.cursor() as cur: with conn.cursor() as cur:
@ -962,6 +997,18 @@ def get_organization_devices(
return {"success": True, "devices": fetch_devices_for_organization(organization_id)} return {"success": True, "devices": fetch_devices_for_organization(organization_id)}
@app.get("/api/v1/devices")
def list_all_devices(authorization: str | None = Header(default=None)):
if not require_service_token(authorization):
return {
"success": False,
"error": "unauthorized",
"message": "Fehlendes oder ungültiges Service-Token.",
}
return {"success": True, "devices": fetch_all_devices()}
@app.get("/api/v1/organizations") @app.get("/api/v1/organizations")
def list_organizations(authorization: str | None = Header(default=None)): def list_organizations(authorization: str | None = Header(default=None)):
if not require_service_token(authorization): if not require_service_token(authorization):