fix(blocklist): get_candidate for O(1) push/unblock, 400 on malformed device_names JSON
This commit is contained in:
parent
b4d9944a2f
commit
30bf151c80
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.ingest.tautulli import parse_webhook as _parse_tautulli
|
||||||
from app.services.blocklist import (
|
from app.services.blocklist import (
|
||||||
BlocklistCandidate,
|
BlocklistCandidate,
|
||||||
|
get_candidate,
|
||||||
list_candidates,
|
list_candidates,
|
||||||
load_telemetry_rules,
|
load_telemetry_rules,
|
||||||
mark_pushed,
|
mark_pushed,
|
||||||
|
|
@ -591,7 +592,7 @@ def scan_blocklist(background_tasks: BackgroundTasks) -> dict:
|
||||||
try:
|
try:
|
||||||
device_map = json.loads(raw_devices)
|
device_map = json.loads(raw_devices)
|
||||||
except (ValueError, TypeError):
|
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_path = PATTERN_DIR / "telemetry.yaml"
|
||||||
telemetry_rules = load_telemetry_rules(telemetry_path) if telemetry_path.exists() else []
|
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)
|
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}")
|
@router.post("/api/blocklist/push/{candidate_id}")
|
||||||
def push_to_pihole(candidate_id: str) -> dict:
|
def push_to_pihole(candidate_id: str) -> dict:
|
||||||
candidates = list_candidates(DB_PATH)
|
try:
|
||||||
candidate = next((c for c in candidates if c.id == candidate_id), None)
|
candidate = get_candidate(DB_PATH, candidate_id)
|
||||||
if candidate is None:
|
except KeyError:
|
||||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||||
if candidate.status != "approved":
|
if candidate.status != "approved":
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -628,9 +629,9 @@ def push_to_pihole(candidate_id: str) -> dict:
|
||||||
|
|
||||||
@router.delete("/api/blocklist/push/{candidate_id}")
|
@router.delete("/api/blocklist/push/{candidate_id}")
|
||||||
def unblock_from_pihole(candidate_id: str) -> dict:
|
def unblock_from_pihole(candidate_id: str) -> dict:
|
||||||
candidates = list_candidates(DB_PATH)
|
try:
|
||||||
candidate = next((c for c in candidates if c.id == candidate_id), None)
|
candidate = get_candidate(DB_PATH, candidate_id)
|
||||||
if candidate is None:
|
except KeyError:
|
||||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||||
if candidate.status != "pushed":
|
if candidate.status != "pushed":
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,15 @@ def _get_candidate(conn: sqlite3.Connection, candidate_id: str) -> BlocklistCand
|
||||||
return _row_to_candidate(row)
|
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:
|
def update_candidate_status(db_path: Path, candidate_id: str, new_status: str) -> BlocklistCandidate:
|
||||||
if new_status not in _VALID_STATUSES:
|
if new_status not in _VALID_STATUSES:
|
||||||
raise ValueError(f"Invalid status {new_status!r}. Must be one of {_VALID_STATUSES}")
|
raise ValueError(f"Invalid status {new_status!r}. Must be one of {_VALID_STATUSES}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue