fix(blocklist): get_candidate for O(1) push/unblock, 400 on malformed device_names JSON
This commit is contained in:
parent
e44c6fd680
commit
7f63f155e2
2 changed files with 17 additions and 7 deletions
15
app/rest.py
15
app/rest.py
|
|
@ -29,6 +29,7 @@ from app.ingest.base import load_compiled_patterns
|
|||
from app.ingest.tautulli import parse_webhook as _parse_tautulli
|
||||
from app.services.blocklist import (
|
||||
BlocklistCandidate,
|
||||
get_candidate,
|
||||
list_candidates,
|
||||
load_telemetry_rules,
|
||||
mark_pushed,
|
||||
|
|
@ -591,7 +592,7 @@ def scan_blocklist(background_tasks: BackgroundTasks) -> dict:
|
|||
try:
|
||||
device_map = json.loads(raw_devices)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
raise HTTPException(status_code=400, detail="device_names is not valid JSON — update it in Settings")
|
||||
telemetry_path = PATTERN_DIR / "telemetry.yaml"
|
||||
telemetry_rules = load_telemetry_rules(telemetry_path) if telemetry_path.exists() else []
|
||||
background_tasks.add_task(run_scan, DB_PATH, source_ids, device_map, telemetry_rules)
|
||||
|
|
@ -611,9 +612,9 @@ def update_blocklist_status(candidate_id: str, body: BlocklistStatusBody) -> dic
|
|||
|
||||
@router.post("/api/blocklist/push/{candidate_id}")
|
||||
def push_to_pihole(candidate_id: str) -> dict:
|
||||
candidates = list_candidates(DB_PATH)
|
||||
candidate = next((c for c in candidates if c.id == candidate_id), None)
|
||||
if candidate is None:
|
||||
try:
|
||||
candidate = get_candidate(DB_PATH, candidate_id)
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||
if candidate.status != "approved":
|
||||
raise HTTPException(
|
||||
|
|
@ -628,9 +629,9 @@ def push_to_pihole(candidate_id: str) -> dict:
|
|||
|
||||
@router.delete("/api/blocklist/push/{candidate_id}")
|
||||
def unblock_from_pihole(candidate_id: str) -> dict:
|
||||
candidates = list_candidates(DB_PATH)
|
||||
candidate = next((c for c in candidates if c.id == candidate_id), None)
|
||||
if candidate is None:
|
||||
try:
|
||||
candidate = get_candidate(DB_PATH, candidate_id)
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||
if candidate.status != "pushed":
|
||||
raise HTTPException(
|
||||
|
|
|
|||
|
|
@ -253,6 +253,15 @@ def _get_candidate(conn: sqlite3.Connection, candidate_id: str) -> BlocklistCand
|
|||
return _row_to_candidate(row)
|
||||
|
||||
|
||||
def get_candidate(db_path: Path, candidate_id: str) -> BlocklistCandidate:
|
||||
"""Fetch a single candidate by ID. Raises KeyError if not found."""
|
||||
conn = sqlite3.connect(str(db_path))
|
||||
try:
|
||||
return _get_candidate(conn, candidate_id)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def update_candidate_status(db_path: Path, candidate_id: str, new_status: str) -> BlocklistCandidate:
|
||||
if new_status not in _VALID_STATUSES:
|
||||
raise ValueError(f"Invalid status {new_status!r}. Must be one of {_VALID_STATUSES}")
|
||||
|
|
|
|||
Loading…
Reference in a new issue