"""Docker network management endpoints.""" from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel from sqlmodel import Session from auth import get_current_user, require_admin from database import get_session from docker_client import DockerError from models.user import User from services import audit_service, network_service router = APIRouter(prefix="/api/networks", tags=["networks"]) _STATUS = {"invalid_request": 400, "forbidden": 403, "not_found": 404} def _ip(request: Request) -> str: return request.client.host if request.client else "unknown" def _map(exc: DockerError): code = _STATUS.get(exc.error) if code: raise HTTPException(status_code=code, detail=exc.detail or exc.error) raise exc # falls through to the global 502 DockerError handler class NetworkCreate(BaseModel): name: str driver: str = "bridge" subnet: str | None = None gateway: str | None = None internal: bool = False attachable: bool = True @router.get("") def list_networks(_user: User = Depends(get_current_user)) -> list[dict]: return network_service.list_networks() @router.get("/{network_id}") def inspect_network(network_id: str, _user: User = Depends(get_current_user)) -> dict: return network_service.inspect_network(network_id) @router.post("", status_code=201) def create_network( body: NetworkCreate, request: Request, session: Session = Depends(get_session), user: User = Depends(require_admin), ) -> dict: try: result = network_service.create_network(body.model_dump()) except DockerError as exc: _map(exc) audit_service.record( session, user=user.username, action="network.create", target=body.name, detail=body.driver, ip=_ip(request), ) return result @router.delete("/{network_id}") def delete_network( network_id: str, request: Request, session: Session = Depends(get_session), user: User = Depends(require_admin), ) -> dict: try: network_service.delete_network(network_id) except DockerError as exc: _map(exc) audit_service.record( session, user=user.username, action="network.delete", target=network_id, ip=_ip(request), ) return {"ok": True} @router.post("/prune") def prune_networks( request: Request, session: Session = Depends(get_session), user: User = Depends(require_admin), ) -> dict: result = network_service.prune_networks() audit_service.record( session, user=user.username, action="network.prune", target="networks", detail=str(result.get("NetworksDeleted") or []), ip=_ip(request), ) return result