Files
Unraid-AppOps-Gateway-Public/backend/app/services/exposure_preferences.py
T

53 lines
2.5 KiB
Python

"""Non-secret exposure diagnostics preferences, independent of NPM ACL policy."""
from sqlalchemy.exc import SQLAlchemyError
from sqlmodel import Session, select
from ..core.time import utc_now
from ..db import session as database
from ..db.models import AppSetting
from ..schemas.exposure_preferences import ExposurePreferences, ExposurePreferencesUpdate
from .audit_logger import log_event
EXPOSURE_PREFERENCES_KEY = "exposure:preferences"
def get_exposure_preferences(session: Session) -> ExposurePreferences:
row = session.get(AppSetting, EXPOSURE_PREFERENCES_KEY)
value = row.value_json if row and isinstance(row.value_json, dict) else {}
# Only an explicit stored boolean false disables diagnostics. Corrupt or
# missing configuration keeps the secure default without crashing reads.
return ExposurePreferences(nginxAccessListChecksEnabled=value.get("nginxAccessListChecksEnabled") is not False)
def runtime_nginx_access_list_checks_enabled() -> bool:
"""Read the same persisted flag for connectors running outside API routes."""
try:
with Session(database.engine) as session:
return get_exposure_preferences(session).nginxAccessListChecksEnabled
except SQLAlchemyError:
return True
def update_exposure_preferences(session: Session, payload: ExposurePreferencesUpdate, *, identity: str) -> ExposurePreferences:
before = get_exposure_preferences(session)
after = ExposurePreferences(**payload.model_dump())
if before == after:
return after
row = session.get(AppSetting, EXPOSURE_PREFERENCES_KEY) or AppSetting(key=EXPOSURE_PREFERENCES_KEY)
row.value_json = after.model_dump()
row.is_secret = False
row.updated_at = utc_now()
session.add(row)
# Derived persistent snapshots must not show warnings from the previous
# preference. Their signatures also include the effective boolean.
for cached in session.exec(select(AppSetting)).all():
if cached.key in {"network_exposure:cache", "safety_center:dashboard_cache"} or cached.key.startswith("ai_security:review_cache:"):
session.delete(cached)
log_event(
session, source="manual", identity=identity, action_id="settings.exposure.update",
target=EXPOSURE_PREFERENCES_KEY, target_type="setting", risk="low",
policy_decision="allowed", reason="Administrator updated NPM access-list diagnostics preference",
result="success", before_state=before.model_dump(), after_state=after.model_dump(),
)
return after