"""Datenquellen verbinden und testen.""" from typing import Annotated from fastapi import APIRouter, Form, Request from fastapi.concurrency import run_in_threadpool from fastapi.responses import HTMLResponse, Response from app import web from app.core.errors import Invalid from app.data_sources import service as sources from app.data_sources.connectors.pull_requests import PROVIDERS from app.workspaces import service as workspaces def router() -> APIRouter: r = APIRouter() @r.get("/workspaces/{workspace_id}/sources/new") def new(request: Request, principal: web.User, workspace_id: int) -> HTMLResponse: with web.db(request).session() as session: workspace = workspaces.require_admin(session, principal, workspace_id).workspace return web.render(request, "source_new.html", {"workspace": workspace, "current_workspace": workspace, "form": {}, "allow_local": web.settings(request).git_allow_local, "providers": PROVIDERS}) @r.post("/workspaces/{workspace_id}/sources") def create(request: Request, principal: web.Checked, workspace_id: int, name: Annotated[str, Form()], url: Annotated[str, Form()], branch: Annotated[str, Form()] = "main", token: Annotated[str, Form()] = "", exposure_confirmed: Annotated[bool, Form()] = False, pr_provider: Annotated[str, Form()] = "none", delete_branches: Annotated[str, Form()] = "1", username: Annotated[str, Form()] = "") -> Response: settings = web.settings(request) try: with web.db(request).session() as session: source = sources.create_git(session, principal, settings, web.vault(request), workspace_id, name=name, url=url, branch=branch, token=token, exposure_confirmed=exposure_confirmed, pr_provider=pr_provider, delete_branches=delete_branches == "1", username=username) except Invalid as e: with web.db(request).session() as session: workspace = workspaces.require_admin(session, principal, workspace_id).workspace # Das Token wird nicht zurück ins Formular geschrieben form = {"name": name, "url": url, "branch": branch, "exposure_confirmed": exposure_confirmed, "pr_provider": pr_provider, "delete_branches": delete_branches == "1", "username": username} return web.render(request, "source_new.html", {"workspace": workspace, "current_workspace": workspace, "form": form, "error": str(e), "allow_local": settings.git_allow_local, "providers": PROVIDERS}, 400) # Gleich testen, damit der Chat ohne zusätzlichen Klick verfügbar wird test(request, principal, source.id) return web.redirect(f"/workspaces/{workspace_id}/data") @r.post("/sources/{source_id}/test") async def test_route(request: Request, principal: web.Checked, source_id: int) -> HTMLResponse: source, membership = await run_in_threadpool(test, request, principal, source_id) return web.render(request, "_source_row.html", {"s": source, "membership": membership}) @r.get("/sources/{source_id}/edit") def edit(request: Request, principal: web.User, source_id: int, error: str = "", status: int = 200) -> HTMLResponse: with web.db(request).session() as session: source = sources.require_testable(session, principal, source_id) workspace = workspaces.get(session, principal, source.workspace_id).workspace return web.render(request, "source_edit.html", {"source": source, "workspace": workspace, "error": error, "current_workspace": workspace, "providers": PROVIDERS}, status) @r.post("/sources/{source_id}") def update(request: Request, principal: web.Checked, source_id: int, name: Annotated[str, Form()], branch: Annotated[str, Form()] = "main", token: Annotated[str, Form()] = "", remove_token: Annotated[bool, Form()] = False, pr_provider: Annotated[str, Form()] = "none", delete_branches: Annotated[str, Form()] = "1", username: Annotated[str, Form()] = "") -> Response: try: with web.db(request).session() as session: source = sources.update_git(session, principal, web.settings(request), web.vault(request), source_id, name=name, branch=branch, token=token, remove_token=remove_token, pr_provider=pr_provider, delete_branches=delete_branches == "1", username=username) except Invalid as e: with web.db(request).session() as session: source = sources.require_testable(session, principal, source_id) workspace = workspaces.get(session, principal, source.workspace_id).workspace return web.render(request, "source_edit.html", {"source": source, "workspace": workspace, "current_workspace": workspace, "error": str(e), "providers": PROVIDERS}, 400) test(request, principal, source.id) return web.redirect(f"/workspaces/{source.workspace_id}/data") @r.post("/sources/{source_id}/delete") def delete(request: Request, principal: web.Checked, source_id: int) -> Response: with web.db(request).session() as session: workspace_id = sources.delete(session, principal, source_id) return web.redirect(f"/workspaces/{workspace_id}/data") return r def test(request: Request, principal, source_id: int): """Test außerhalb einer Transaktion ausführen, Ergebnis danach speichern.""" db, settings = web.db(request), web.settings(request) with db.session() as session: source = sources.require_testable(session, principal, source_id) result = sources.run_test(source, settings, web.vault(request)) with db.session() as session: sources.save_test(session, principal, source_id, result) source = sources.get(session, principal, source_id) membership = workspaces.get(session, principal, source.workspace_id) return source, membership