BoltClam 1.0.0: ClamAV desktop protection with Bolt sign-in
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>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
from boltclam.api_client import ApiClient
|
||||
from boltclam.auth import AuthService, CredentialStore
|
||||
from boltclam.clamav import ClamAVService
|
||||
from boltclam.config import AccountCache, SettingsStore
|
||||
from boltclam.context import AppContext
|
||||
from boltclam.quarantine import QuarantineService
|
||||
from boltclam.storage import Storage
|
||||
from boltclam.ui.login_dialog import LoginDialog
|
||||
from boltclam.ui.main_window import MainWindow
|
||||
|
||||
ACCOUNT = {
|
||||
"user": {"id": "1", "email": "aaron@example.com", "name": "Aaron",
|
||||
"username": "aaron"},
|
||||
"subscription": {"tier": "premium", "label": "Premium", "status": "active",
|
||||
"current_period_end": "2026-12-01T00:00:00Z"},
|
||||
"balance": {"weekly_remaining": 100, "topup": 0, "allowed": True},
|
||||
"features": {"licensed": True},
|
||||
}
|
||||
|
||||
|
||||
class FakeApi:
|
||||
def get_account(self):
|
||||
return ACCOUNT
|
||||
|
||||
def get_updates(self, *args, **kwargs):
|
||||
raise RuntimeError("offline")
|
||||
|
||||
|
||||
def _context(tmp_path) -> AppContext:
|
||||
store = SettingsStore()
|
||||
store.save(store.load())
|
||||
settings = store.update(last_update_check=time.time(), logging_enabled=False,
|
||||
realtime_enabled=False)
|
||||
storage = Storage()
|
||||
quarantine = QuarantineService(storage, tmp_path / "quarantine")
|
||||
auth = AuthService(
|
||||
"http://127.0.0.1:9", install_id=settings.install_id,
|
||||
credentials=CredentialStore(tmp_path / "credentials.dat"),
|
||||
account_cache=AccountCache(tmp_path / "account.json"))
|
||||
return AppContext(
|
||||
settings_store=store, settings=settings, storage=storage,
|
||||
quarantine=quarantine, clamav=ClamAVService(settings.clamav_path),
|
||||
auth=auth, session_key="bolt_live_fake", account=ACCOUNT,
|
||||
install_id=settings.install_id, api=FakeApi())
|
||||
|
||||
|
||||
def test_main_window_builds_four_pages_and_switches_tabs(qapp, isolated_env):
|
||||
context = _context(isolated_env)
|
||||
window = MainWindow(context)
|
||||
try:
|
||||
window.show()
|
||||
qapp.processEvents()
|
||||
assert window.stack.count() == 4
|
||||
assert [button.text() for button in window.nav_buttons] == [
|
||||
"Homepage", "Scan & results", "About & updates", "Settings"]
|
||||
assert window.scan_page.tabs.currentIndex() == 0
|
||||
window.scan_page.tabs.setCurrentIndex(1)
|
||||
assert window.scan_page.tabs.currentIndex() == 1
|
||||
window._navigate(3)
|
||||
assert window.stack.currentIndex() == 3
|
||||
assert window.settings_page.channel_combo.currentData() == "release"
|
||||
assert window.about_page.rows["account"].value_label.text() == "Aaron"
|
||||
finally:
|
||||
window._allow_close = True
|
||||
window.close()
|
||||
qapp.processEvents()
|
||||
|
||||
|
||||
def test_login_dialog_builds_without_starting_a_worker(qapp, isolated_env):
|
||||
auth = AuthService(
|
||||
"http://127.0.0.1:9", install_id="test",
|
||||
credentials=CredentialStore(isolated_env / "credentials.dat"),
|
||||
account_cache=AccountCache(isolated_env / "account.json"))
|
||||
dialog = LoginDialog(auth, notice="Test notice")
|
||||
try:
|
||||
assert "BoltClam" in dialog.windowTitle()
|
||||
assert dialog.browser_button.isEnabled()
|
||||
assert dialog.session is None
|
||||
finally:
|
||||
dialog.reject()
|
||||
Reference in New Issue
Block a user