Files
AWatch-rus/aw-server/dlp-case-management/case_service.py
T

92 lines
3.2 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import os
from pathlib import Path
from typing import Any
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from case_rules import is_self_test_case
from case_schema import CaseCommentCreate, CaseCreate, CaseHayabusaLink, CaseUpdate
from case_storage import CaseStorage, ForensicsHostMismatchError
DB = Path(os.environ.get("AW_DLP_CASE_DB_PATH", "/opt/activitywatch/dlp-case-management/cases.db"))
APP = FastAPI(title="AWatch DLP Case Management")
APP.add_middleware(
CORSMiddleware,
allow_origins=["http://127.0.0.1:5600", "http://localhost:5600", "http://10.10.10.13:5600", "*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
STORE = CaseStorage(DB)
@APP.get("/health")
def health() -> dict[str, Any]:
return {"ok": True, "db": str(DB)}
@APP.post("/api/0/dlp/cases")
def create_case(payload: CaseCreate) -> dict[str, Any]:
if is_self_test_case(payload.incident_id, payload.title):
raise HTTPException(status_code=422, detail="self_test cases are not allowed")
return STORE.create_case(payload.model_dump(exclude_none=True), actor="api")
@APP.get("/api/0/dlp/cases")
def list_cases(
status: str | None = Query(default=None),
host: str | None = Query(default=None),
limit: int = Query(default=200, ge=1, le=2000),
) -> list[dict[str, Any]]:
return STORE.list_cases(status=status, host=host, limit=limit)
@APP.get("/api/0/dlp/cases/{case_id}")
def get_case(case_id: int) -> dict[str, Any]:
try:
case = STORE.get_case(case_id)
except KeyError:
raise HTTPException(status_code=404, detail="case not found")
case["comments"] = STORE.list_comments(case_id, limit=200)
case["audit"] = STORE.list_audit(case_id, limit=200)
return case
@APP.patch("/api/0/dlp/cases/{case_id}")
def update_case(case_id: int, payload: CaseUpdate) -> dict[str, Any]:
patch = payload.model_dump(exclude_none=True)
if not patch:
return STORE.get_case(case_id)
try:
return STORE.update_case(case_id, patch=patch, actor="api")
except KeyError:
raise HTTPException(status_code=404, detail="case not found")
@APP.post("/api/0/dlp/cases/{case_id}/comments")
def add_comment(case_id: int, payload: CaseCommentCreate) -> dict[str, Any]:
try:
STORE.get_case(case_id)
except KeyError:
raise HTTPException(status_code=404, detail="case not found")
return STORE.add_comment(case_id=case_id, comment=payload.comment, author=payload.author)
@APP.get("/api/0/dlp/cases/{case_id}/comments")
def list_comments(case_id: int, limit: int = Query(default=200, ge=1, le=2000)) -> list[dict[str, Any]]:
return STORE.list_comments(case_id=case_id, limit=limit)
@APP.post("/api/0/dlp/cases/{case_id}/forensics/hayabusa")
def link_hayabusa(case_id: int, payload: CaseHayabusaLink) -> dict[str, Any]:
try:
return STORE.link_hayabusa(case_id=case_id, payload=payload.model_dump(exclude_none=True), actor="api")
except ForensicsHostMismatchError as exc:
raise HTTPException(status_code=409, detail=str(exc))
except KeyError:
raise HTTPException(status_code=404, detail="case not found")