dashboard-nanobot/backend/services/platform_system_settings_se...

192 lines
7.5 KiB
Python

import json
from typing import Any, Dict, List
from sqlmodel import Session, select
from models.platform import PlatformSetting
from schemas.platform import SystemSettingPayload
from services.platform_settings_core import (
ACTIVITY_EVENT_RETENTION_SETTING_KEY,
DEFAULT_ACTIVITY_EVENT_RETENTION_DAYS,
DEPRECATED_SETTING_KEYS,
PROTECTED_SETTING_KEYS,
SETTING_KEYS,
SYSTEM_SETTING_DEFINITIONS,
_bootstrap_platform_setting_values,
_normalize_activity_event_retention_days,
_normalize_setting_key,
_read_setting_value,
_setting_item_from_row,
_upsert_setting_row,
_utcnow,
)
def _coerce_auth_ttl_hours_from_legacy(value: Any) -> int:
try:
normalized = int(value)
except Exception:
normalized = 0
return max(1, min(720, normalized * 24))
def ensure_default_system_settings(session: Session) -> None:
bootstrap_values = _bootstrap_platform_setting_values()
legacy_row = session.get(PlatformSetting, "global")
if legacy_row is not None:
try:
legacy_data = _read_setting_value(legacy_row)
except Exception:
legacy_data = {}
if isinstance(legacy_data, dict):
for key in SETTING_KEYS:
meta = SYSTEM_SETTING_DEFINITIONS[key]
_upsert_setting_row(
session,
key,
name=str(meta["name"]),
category=str(meta["category"]),
description=str(meta["description"]),
value_type=str(meta["value_type"]),
value=legacy_data.get(key, bootstrap_values.get(key, meta["value"])),
is_public=bool(meta["is_public"]),
sort_order=int(meta["sort_order"]),
)
session.delete(legacy_row)
session.commit()
legacy_auth_ttl_hours = None
dirty = False
for key in DEPRECATED_SETTING_KEYS:
legacy_row = session.get(PlatformSetting, key)
if legacy_row is not None:
if key in {"sys_auth_token_ttl_days", "auth_token_ttl_days"} and legacy_auth_ttl_hours is None:
try:
legacy_auth_ttl_hours = _coerce_auth_ttl_hours_from_legacy(_read_setting_value(legacy_row))
except Exception:
legacy_auth_ttl_hours = None
session.delete(legacy_row)
dirty = True
for key, meta in SYSTEM_SETTING_DEFINITIONS.items():
row = session.get(PlatformSetting, key)
default_value = bootstrap_values.get(key, meta["value"])
if key == "auth_token_ttl_hours" and legacy_auth_ttl_hours is not None:
default_value = legacy_auth_ttl_hours
if row is None:
_upsert_setting_row(
session,
key,
name=str(meta["name"]),
category=str(meta["category"]),
description=str(meta["description"]),
value_type=str(meta["value_type"]),
value=default_value,
is_public=bool(meta["is_public"]),
sort_order=int(meta["sort_order"]),
)
dirty = True
continue
changed = False
if key == "auth_token_ttl_hours" and legacy_auth_ttl_hours is not None:
try:
current_value = int(_read_setting_value(row))
except Exception:
current_value = int(meta["value"])
if current_value == int(meta["value"]) and legacy_auth_ttl_hours != current_value:
row.value_type = str(meta["value_type"])
row.value_json = json.dumps(legacy_auth_ttl_hours, ensure_ascii=False)
changed = True
for field in ("name", "category", "description", "value_type"):
value = str(meta[field])
if key in PROTECTED_SETTING_KEYS:
if getattr(row, field) != value:
setattr(row, field, value)
changed = True
elif not getattr(row, field):
setattr(row, field, value)
changed = True
if key in PROTECTED_SETTING_KEYS:
if int(getattr(row, "sort_order", 100) or 100) != int(meta["sort_order"]):
row.sort_order = int(meta["sort_order"])
changed = True
if bool(getattr(row, "is_public", False)) != bool(meta["is_public"]):
row.is_public = bool(meta["is_public"])
changed = True
elif getattr(row, "sort_order", None) is None:
row.sort_order = int(meta["sort_order"])
changed = True
if key not in PROTECTED_SETTING_KEYS and getattr(row, "is_public", None) is None:
row.is_public = bool(meta["is_public"])
changed = True
if changed:
row.updated_at = _utcnow()
session.add(row)
dirty = True
if dirty:
session.commit()
def list_system_settings(session: Session, search: str = "") -> List[Dict[str, Any]]:
ensure_default_system_settings(session)
stmt = select(PlatformSetting).order_by(PlatformSetting.sort_order.asc(), PlatformSetting.key.asc())
rows = session.exec(stmt).all()
keyword = str(search or "").strip().lower()
items = [_setting_item_from_row(row) for row in rows]
if not keyword:
return items
return [
item
for item in items
if keyword in str(item["key"]).lower()
or keyword in str(item["name"]).lower()
or keyword in str(item["category"]).lower()
or keyword in str(item["description"]).lower()
]
def create_or_update_system_setting(session: Session, payload: SystemSettingPayload) -> Dict[str, Any]:
ensure_default_system_settings(session)
normalized_key = _normalize_setting_key(payload.key)
definition = SYSTEM_SETTING_DEFINITIONS.get(normalized_key, {})
row = _upsert_setting_row(
session,
payload.key,
name=payload.name or str(definition.get("name") or payload.key),
category=payload.category or str(definition.get("category") or "general"),
description=payload.description or str(definition.get("description") or ""),
value_type=payload.value_type or str(definition.get("value_type") or "json"),
value=payload.value if payload.value is not None else definition.get("value"),
is_public=payload.is_public,
sort_order=payload.sort_order or int(definition.get("sort_order") or 100),
)
if normalized_key == ACTIVITY_EVENT_RETENTION_SETTING_KEY:
from services.platform_activity_service import prune_expired_activity_events
prune_expired_activity_events(session, force=True)
session.commit()
session.refresh(row)
return _setting_item_from_row(row)
def delete_system_setting(session: Session, key: str) -> None:
normalized_key = _normalize_setting_key(key)
if normalized_key in PROTECTED_SETTING_KEYS:
raise ValueError("Core platform settings cannot be deleted")
row = session.get(PlatformSetting, normalized_key)
if row is None:
raise ValueError("Setting not found")
session.delete(row)
session.commit()
def get_activity_event_retention_days(session: Session) -> int:
row = session.get(PlatformSetting, ACTIVITY_EVENT_RETENTION_SETTING_KEY)
if row is None:
return DEFAULT_ACTIVITY_EVENT_RETENTION_DAYS
try:
value = _read_setting_value(row)
except Exception:
value = DEFAULT_ACTIVITY_EVENT_RETENTION_DAYS
return _normalize_activity_event_retention_days(value)