feat(dlp): implement case management service and DLP Review integration
This commit is contained in:
@@ -1,53 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
from fastapi import FastAPI, HTTPException, Query
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
DB = Path("/opt/activitywatch/dlp-case-management/cases.db")
|
||||
from case_schema import CaseCommentCreate, CaseCreate, CaseUpdate
|
||||
from case_storage import CaseStorage
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class CaseCreate(BaseModel):
|
||||
incident_id: str
|
||||
title: str
|
||||
severity: str = "medium"
|
||||
assignee: str | None = None
|
||||
|
||||
|
||||
def _conn() -> sqlite3.Connection:
|
||||
DB.parent.mkdir(parents=True, exist_ok=True)
|
||||
c = sqlite3.connect(DB)
|
||||
c.execute(
|
||||
"CREATE TABLE IF NOT EXISTS cases (id INTEGER PRIMARY KEY, incident_id TEXT, title TEXT, severity TEXT, assignee TEXT, status TEXT DEFAULT 'open')"
|
||||
)
|
||||
return c
|
||||
@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]:
|
||||
c = _conn()
|
||||
cur = c.cursor()
|
||||
cur.execute(
|
||||
"INSERT INTO cases (incident_id,title,severity,assignee,status) VALUES (?,?,?,?,?)",
|
||||
(payload.incident_id, payload.title, payload.severity, payload.assignee, "open"),
|
||||
)
|
||||
c.commit()
|
||||
case_id = cur.lastrowid
|
||||
c.close()
|
||||
return {"id": case_id}
|
||||
return STORE.create_case(payload.model_dump(exclude_none=True), actor="api")
|
||||
|
||||
|
||||
@APP.get("/api/0/dlp/cases")
|
||||
def list_cases() -> list[dict[str, Any]]:
|
||||
c = _conn()
|
||||
rows = c.execute("SELECT id,incident_id,title,severity,assignee,status FROM cases ORDER BY id DESC").fetchall()
|
||||
c.close()
|
||||
return [
|
||||
{"id": r[0], "incident_id": r[1], "title": r[2], "severity": r[3], "assignee": r[4], "status": r[5]}
|
||||
for r in rows
|
||||
]
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user