78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, HTTPException, Request, Response, status
|
|
|
|
from app.automations.models import (
|
|
AutomationProposal,
|
|
ProposalDecision,
|
|
ProposalStatus,
|
|
)
|
|
from app.automations.store import AutomationStore
|
|
|
|
router = APIRouter(prefix="/v1/automations", tags=["automations"])
|
|
|
|
|
|
@router.post("/proposals", response_model=AutomationProposal, status_code=201)
|
|
def create_proposal(payload: AutomationProposal, request: Request) -> AutomationProposal:
|
|
if payload.trigger.above is None and payload.trigger.below is None:
|
|
raise HTTPException(status_code=422, detail="Trigger benötigt above oder below.")
|
|
return _store(request).create(payload.model_copy(update={"status": ProposalStatus.DRAFT}))
|
|
|
|
|
|
@router.get("/proposals", response_model=list[AutomationProposal])
|
|
def list_proposals(request: Request) -> list[AutomationProposal]:
|
|
return _store(request).list()
|
|
|
|
|
|
@router.post("/proposals/{proposal_id}/approve", response_model=AutomationProposal)
|
|
def approve(
|
|
proposal_id: str,
|
|
payload: ProposalDecision,
|
|
request: Request,
|
|
) -> AutomationProposal:
|
|
return _decide(request, proposal_id, ProposalStatus.APPROVED, payload.expected_revision)
|
|
|
|
|
|
@router.post("/proposals/{proposal_id}/reject", response_model=AutomationProposal)
|
|
def reject(
|
|
proposal_id: str,
|
|
payload: ProposalDecision,
|
|
request: Request,
|
|
) -> AutomationProposal:
|
|
return _decide(request, proposal_id, ProposalStatus.REJECTED, payload.expected_revision)
|
|
|
|
|
|
@router.get("/proposals/{proposal_id}/yaml")
|
|
def export_yaml(proposal_id: str, request: Request) -> Response:
|
|
try:
|
|
content = _store(request).export_yaml(proposal_id)
|
|
except KeyError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
|
return Response(content=content, media_type="application/yaml")
|
|
|
|
|
|
def _decide(
|
|
request: Request,
|
|
proposal_id: str,
|
|
decision: ProposalStatus,
|
|
expected_revision: int,
|
|
) -> AutomationProposal:
|
|
try:
|
|
return _store(request).decide(proposal_id, decision, expected_revision)
|
|
except KeyError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
|
|
|
|
|
def _store(request: Request) -> AutomationStore:
|
|
store = getattr(request.app.state, "automation_store", None)
|
|
if not isinstance(store, AutomationStore):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Automation Store nicht initialisiert.",
|
|
)
|
|
return store
|