Initial commit: AegisSight-Monitor-Verwaltung
Dieser Commit ist enthalten in:
116
src/routers/organizations.py
Normale Datei
116
src/routers/organizations.py
Normale Datei
@@ -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()
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren