Adds the PyQt6 Windows client (Homepage, Scan & results, About & updates, Settings), ClamAV scanning and quarantine, browser-download watch with an exclusive scan gate, Bolt loopback/PKCE sign-in with DPAPI key storage, Gitea release feed with checksum verification, opt-in diagnostics, and Windows/portable build tooling. Co-Authored-By: Claude Code <noreply@anthropic.com>
66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from boltclam.models import Detection, QuarantineItem, RealtimeEvent
|
|
from boltclam.storage import Storage
|
|
|
|
|
|
def _storage(tmp_path) -> Storage:
|
|
return Storage(tmp_path / "history.db")
|
|
|
|
|
|
def test_scan_and_detection_lifecycle(tmp_path):
|
|
storage = _storage(tmp_path)
|
|
scan_id = storage.create_scan("homes", [r"C:\Users"], engine_version="1.4.3",
|
|
db_version="27452")
|
|
assert scan_id == 1
|
|
detection = Detection(path=r"C:\Users\a\bad.exe", signature="Win.Test", size=42)
|
|
detection.id = storage.add_detection(scan_id, detection)
|
|
storage.finish_scan(scan_id, status="completed", scanned_files=100,
|
|
infected_files=1, errors=2, duration_seconds=12.5,
|
|
cancelled=False)
|
|
|
|
record = storage.get_scan(scan_id)
|
|
assert record is not None
|
|
assert record.scope == "homes"
|
|
assert record.scope_label == "User homes"
|
|
assert record.scanned_files == 100
|
|
assert record.errors == 2
|
|
assert record.paths == [r"C:\Users"]
|
|
assert record.detections[0].signature == "Win.Test"
|
|
|
|
stats = storage.stats()
|
|
assert stats["active_threats"] == 1
|
|
assert stats["latest_scan"].id == scan_id
|
|
|
|
storage.update_detection_action(detection.id, "quarantined", "Q-1")
|
|
assert storage.stats()["active_threats"] == 0
|
|
assert storage.recent_detections()[0]["action"] == "quarantined"
|
|
|
|
|
|
def test_quarantine_rows_and_counts(tmp_path):
|
|
storage = _storage(tmp_path)
|
|
item = QuarantineItem(
|
|
id="Q-1", original_path=r"C:\bad.exe", quarantine_path=str(tmp_path / "q.bin"),
|
|
signature="Win.Test", sha256="a" * 64, size=10, created_at="2026-10-25T10:00:00Z",
|
|
scan_id=1)
|
|
storage.add_quarantine(item)
|
|
assert storage.quarantine_count() == 1
|
|
assert storage.get_quarantine("Q-1").signature == "Win.Test"
|
|
storage.set_quarantine_status("Q-1", "restored")
|
|
assert storage.quarantine_count() == 0
|
|
assert storage.list_quarantine()[0].status == "restored"
|
|
|
|
|
|
def test_realtime_events_and_diagnostics_are_serializable(tmp_path):
|
|
storage = _storage(tmp_path)
|
|
storage.add_realtime_event(RealtimeEvent(
|
|
created_at="2026-10-25T10:00:00Z", path=r"C:\Users\a\bad.exe",
|
|
signature="Win.Test", action="quarantined", detail="Locked"))
|
|
events = storage.list_realtime_events()
|
|
assert events[0].action == "quarantined"
|
|
snapshot = storage.diagnostics_snapshot()
|
|
json.dumps(snapshot)
|
|
assert snapshot["realtime"][0]["signature"] == "Win.Test"
|