- Fix save node patching: early exit on matching targets, subgraph traversal, tighten isSaveLikeNode filters - Fix project target prefix handling: dual prefix and filename_prefix support across preview and create_custom_out - Optimize UI: 300ms debounce on target name input, patch nodes preview caching, clean asset name extraction - Backend stability: audit logger fd cleanup, double close fix, registry locks, rate limiting cache eviction - Model fixer: properly clear node errors and refresh combo lists in ComfyUI
62 lines
1.6 KiB
Python
62 lines
1.6 KiB
Python
"""
|
|
Structured audit logging for sensitive operations.
|
|
|
|
Writes JSON Lines events to a file under ComfyUI output/PROJECTS/_INDEX by default.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import threading
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
from typing import Any, Dict
|
|
|
|
from aiohttp import web
|
|
|
|
from .project_store import safe_under_output
|
|
from .route_utils import _get_client_ip
|
|
|
|
|
|
|
|
def _audit_log_path() -> Path:
|
|
rel = (os.environ.get("MJR_AUDIT_LOG_PATH") or "PROJECTS/_INDEX/audit.log").strip()
|
|
return safe_under_output(rel)
|
|
|
|
|
|
class AuditLogger:
|
|
def __init__(self) -> None:
|
|
self._lock = threading.Lock()
|
|
|
|
def log_event(
|
|
self,
|
|
request: web.Request,
|
|
*,
|
|
action: str,
|
|
resource: str,
|
|
details: Dict[str, Any] | None = None,
|
|
success: bool = True,
|
|
) -> None:
|
|
try:
|
|
path = _audit_log_path()
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
event = {
|
|
"ts": datetime.now(timezone.utc).isoformat(),
|
|
"action": str(action),
|
|
"resource": str(resource),
|
|
"client_ip": _get_client_ip(request),
|
|
"success": bool(success),
|
|
"details": details or {},
|
|
}
|
|
line = json.dumps(event, ensure_ascii=True, separators=(",", ":")) + "\n"
|
|
with self._lock:
|
|
with path.open("a", encoding="utf-8") as f:
|
|
f.write(line)
|
|
except Exception:
|
|
# Audit logging must never break the request path.
|
|
return
|
|
|
|
|
|
audit_logger = AuditLogger()
|
|
|