Initial commit: AegisSight-Monitor-Verwaltung

Dieser Commit ist enthalten in:
claude-dev
2026-03-04 17:53:19 +01:00
Commit e5a11d3549
19 geänderte Dateien mit 2421 neuen und 0 gelöschten Zeilen

116
src/routers/organizations.py Normale Datei
Datei anzeigen

@@ -0,0 +1,116 @@
"""Organisations-CRUD."""
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, status
from models import OrgCreate, OrgUpdate, OrgResponse
from auth import get_current_admin
from database import db_dependency
import aiosqlite
router = APIRouter(prefix="/api/orgs", tags=["organizations"])
async def _enrich_org(db: aiosqlite.Connection, row: aiosqlite.Row) -> dict:
org = dict(row)
cursor = await db.execute(
"SELECT COUNT(*) as cnt FROM users WHERE organization_id = ? AND is_active = 1",
(org["id"],),
)
org["user_count"] = (await cursor.fetchone())["cnt"]
cursor = await db.execute(
"SELECT license_type, status FROM licenses WHERE organization_id = ? AND status = 'active' ORDER BY created_at DESC LIMIT 1",
(org["id"],),
)
lic = await cursor.fetchone()
org["license_status"] = lic["status"] if lic else "none"
org["license_type"] = lic["license_type"] if lic else ""
return org
@router.get("", response_model=list[OrgResponse])
async def list_organizations(
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
cursor = await db.execute("SELECT * FROM organizations ORDER BY created_at DESC")
rows = await cursor.fetchall()
return [await _enrich_org(db, row) for row in rows]
@router.post("", response_model=OrgResponse, status_code=status.HTTP_201_CREATED)
async def create_organization(
data: OrgCreate,
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
# Slug-Duplikat pruefen
cursor = await db.execute("SELECT id FROM organizations WHERE slug = ?", (data.slug,))
if await cursor.fetchone():
raise HTTPException(status_code=400, detail="Slug bereits vergeben")
now = datetime.now(timezone.utc).isoformat()
cursor = await db.execute(
"INSERT INTO organizations (name, slug, is_active, created_at, updated_at) VALUES (?, ?, 1, ?, ?)",
(data.name, data.slug, now, now),
)
await db.commit()
cursor = await db.execute("SELECT * FROM organizations WHERE id = ?", (cursor.lastrowid,))
return await _enrich_org(db, await cursor.fetchone())
@router.get("/{org_id}", response_model=OrgResponse)
async def get_organization(
org_id: int,
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
cursor = await db.execute("SELECT * FROM organizations WHERE id = ?", (org_id,))
row = await cursor.fetchone()
if not row:
raise HTTPException(status_code=404, detail="Organisation nicht gefunden")
return await _enrich_org(db, row)
@router.put("/{org_id}", response_model=OrgResponse)
async def update_organization(
org_id: int,
data: OrgUpdate,
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
cursor = await db.execute("SELECT * FROM organizations WHERE id = ?", (org_id,))
row = await cursor.fetchone()
if not row:
raise HTTPException(status_code=404, detail="Organisation nicht gefunden")
updates = {}
if data.name is not None:
updates["name"] = data.name
if data.is_active is not None:
updates["is_active"] = 1 if data.is_active else 0
if updates:
updates["updated_at"] = datetime.now(timezone.utc).isoformat()
set_clause = ", ".join(f"{k} = ?" for k in updates)
values = list(updates.values()) + [org_id]
await db.execute(f"UPDATE organizations SET {set_clause} WHERE id = ?", values)
await db.commit()
cursor = await db.execute("SELECT * FROM organizations WHERE id = ?", (org_id,))
return await _enrich_org(db, await cursor.fetchone())
@router.delete("/{org_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_organization(
org_id: int,
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
cursor = await db.execute("SELECT * FROM organizations WHERE id = ?", (org_id,))
if not await cursor.fetchone():
raise HTTPException(status_code=404, detail="Organisation nicht gefunden")
# Kaskadierendes Loeschen
await db.execute("DELETE FROM organizations WHERE id = ?", (org_id,))
await db.commit()