"""Administration: Teams und Nutzer.""" from typing import Annotated from fastapi import APIRouter, Form, Request from fastapi.responses import HTMLResponse, Response from app import web from app.core.database import now from app.core.errors import Invalid from app.identity import admin from app.uploads import service as uploads Text = Annotated[str, Form()] Flag = Annotated[bool, Form()] def router() -> APIRouter: r = APIRouter() def teams_page(request: Request, principal, error: str = "", status: int = 200) -> HTMLResponse: admin.require(principal) with web.db(request).session() as session: rows = admin.teams(session) return web.render(request, "admin_teams.html", {"rows": rows, "error": error}, status) def team_page(request: Request, principal, team_id: int, error: str = "", notice: str = "", status: int = 200) -> HTMLResponse: admin.require(principal) settings = web.settings(request) with web.db(request).session() as session: workspaces = admin.team_workspaces(session, team_id) context = {"team": admin.get_team(session, team_id), "members": admin.team_members(session, team_id), "workspaces": workspaces, "error": error, "notice": notice, "storage": {w.id: uploads.storage(session, settings, w) for w in workspaces}, "default_storage_mb": settings.workspace_storage_mb} return web.render(request, "admin_team.html", context, status) def users_page(request: Request, principal, error: str = "", notice: str = "", status: int = 200, issued: tuple[str, str] | None = None) -> HTMLResponse: admin.require(principal) with web.db(request).session() as session: context = {"users": admin.users(session), "teams_by_user": admin.teams_by_user(session), "error": error, "notice": notice, "issued": issued, "now": now()} return web.render(request, "admin_users.html", context, status) @r.get("/admin/teams") def teams(request: Request, principal: web.User) -> HTMLResponse: return teams_page(request, principal) @r.post("/admin/teams") def create_team(request: Request, principal: web.Checked, slug: Text, name: Text) -> Response: try: with web.db(request).session() as session: team = admin.save_team(session, principal, None, slug=slug, name=name) except Invalid as e: return teams_page(request, principal, str(e), 400) return web.redirect(f"/admin/teams/{team.id}") @r.get("/admin/teams/{team_id}") def team(request: Request, principal: web.User, team_id: int) -> HTMLResponse: return team_page(request, principal, team_id) def team_action(request: Request, principal, team_id: int, action, notice: str) -> Response: try: with web.db(request).session() as session: action(session) except Invalid as e: return team_page(request, principal, team_id, error=str(e), status=400) return team_page(request, principal, team_id, notice=notice) @r.post("/admin/teams/{team_id}") def update_team(request: Request, principal: web.Checked, team_id: int, slug: Text, name: Text) -> Response: return team_action(request, principal, team_id, lambda s: admin.save_team(s, principal, team_id, slug=slug, name=name), "Gespeichert.") @r.post("/admin/teams/{team_id}/delete") def delete_team(request: Request, principal: web.Checked, team_id: int) -> Response: try: with web.db(request).session() as session: admin.delete_team(session, principal, team_id) except Invalid as e: return team_page(request, principal, team_id, error=str(e), status=400) return web.redirect("/admin/teams") @r.post("/admin/teams/{team_id}/workspaces/{workspace_id}/storage") def set_storage(request: Request, principal: web.Checked, team_id: int, workspace_id: int, limit_mb: Text = "") -> Response: return team_action(request, principal, team_id, lambda s: admin.set_storage_limit(s, principal, workspace_id, limit_mb), "Speicherkontingent gespeichert.") @r.post("/admin/teams/{team_id}/members") def add_member(request: Request, principal: web.Checked, team_id: int, username: Text) -> Response: return team_action(request, principal, team_id, lambda s: admin.add_member(s, principal, team_id, username), "Mitglied hinzugefügt.") @r.post("/admin/teams/{team_id}/members/{user_id}/remove") def remove_member(request: Request, principal: web.Checked, team_id: int, user_id: int) -> Response: return team_action(request, principal, team_id, lambda s: admin.remove_member(s, principal, team_id, user_id), "Entfernt, inklusive aller Workspace-Mitgliedschaften in diesem Team.") @r.get("/admin/users") def users(request: Request, principal: web.User) -> HTMLResponse: return users_page(request, principal) @r.post("/admin/users") def create_user(request: Request, principal: web.Checked, username: Text, display_name: Text = "", is_admin: Flag = False, email: Text = "") -> Response: try: with web.db(request).session() as session: user, secret = admin.create_user(session, principal, username, display_name, is_admin, email) except Invalid as e: return users_page(request, principal, error=str(e), status=400) return users_page(request, principal, issued=(user.username, secret), notice="Nutzer angelegt. Jetzt einem Team zuordnen.") @r.post("/admin/users/{user_id}/reset-password") def reset_password(request: Request, principal: web.Checked, user_id: int) -> Response: with web.db(request).session() as session: user, secret = admin.reset_password(session, principal, user_id) return users_page(request, principal, issued=(user.username, secret), notice="Passwort zurückgesetzt; alle Sitzungen des Nutzers sind beendet.") @r.post("/admin/users/{user_id}") def update_user(request: Request, principal: web.Checked, user_id: int, display_name: Text = "", is_admin: Flag = False, active: Flag = False, is_global_approver: Flag = False, email: Text = "") -> Response: try: with web.db(request).session() as session: admin.update_user(session, principal, user_id, display_name=display_name, is_admin=is_admin, active=active, is_global_approver=is_global_approver, email=email) except Invalid as e: return users_page(request, principal, error=str(e), status=400) return users_page(request, principal, notice="Gespeichert.") return r