feat: configurable bottom handles, scanner rewrite, UI polish
## New features - Configurable bottom connection points per node (1–4 handles) - Fit view on load - LiveView improvements - Node modal: inline Type/Icon picker, default icon in trigger - Remove redundant Save button from ScanConfigModal ## Scanner fixes - Phase 1: replace nmap ARP sweep with concurrent asyncio ping sweep (50 parallel pings, 1s timeout). Zero false positives, works in any Docker network mode. Supplements with /proc/net/arp for ICMP-blocked devices. - Phase 2: explicit -sS (root) / -sT (non-root) scan type; bump host-timeout to 60s; gather(return_exceptions=True) so one failing host doesn't abort the batch - Fix 404 on missing device in hide/ignore - Validate CIDR ranges to prevent nmap injection - Thread-safe cancel set, pre-fetch canvas/hidden IPs (no N+1 queries) - Logging: attach StreamHandler to root logger so app.* logs are visible ## Tests - 21 backend scanner tests (ping sweep, ARP cache, Phase 2 tolerance) - Full NodeModal coverage (53 tests) - LiveView, store, edge label tests
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
import logging.config
|
||||
from collections.abc import AsyncGenerator
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any
|
||||
@@ -14,6 +16,16 @@ from app.db.database import init_db
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
# Ensure app logs are visible: attach a handler to the root logger if none
|
||||
# exists (uvicorn only installs handlers on its own loggers, not the root).
|
||||
root_logger = logging.getLogger()
|
||||
if not root_logger.handlers:
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(logging.Formatter("%(levelname)s:%(name)s:%(message)s"))
|
||||
root_logger.addHandler(handler)
|
||||
root_logger.setLevel(logging.INFO)
|
||||
logging.getLogger("app").setLevel(logging.INFO)
|
||||
logging.getLogger("app.services.scanner").setLevel(logging.INFO)
|
||||
await init_db()
|
||||
settings.load_overrides()
|
||||
start_scheduler()
|
||||
|
||||
Reference in New Issue
Block a user