117 Zeilen
4.2 KiB
Python
117 Zeilen
4.2 KiB
Python
"""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()
|