Files
resolutionflow/backend/app/core/settings_manager.py
Michael Chihlas b570f8415f feat: implement full admin panel with dashboard, user management, and platform settings
Adds complete super_admin panel with 9 pages and account owner categories page.
Backend includes 5 new DB tables, ~25 API endpoints, settings manager with
in-memory cache, and 29 integration tests. Frontend includes reusable admin
components (DataTable, Pagination, ActionMenu, etc.) with code-split lazy loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 06:05:59 -05:00

97 lines
3.1 KiB
Python

"""Runtime platform settings with in-memory cache."""
import json
import time
import uuid
from datetime import datetime, timezone
from typing import Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.platform_setting import PlatformSetting
class SettingsManager:
"""Manage runtime platform settings with in-memory cache (60s TTL)."""
_cache: dict[str, Any] = {}
_cache_time: float = 0
CACHE_TTL = 60
@classmethod
async def get(cls, key: str, db: AsyncSession, default: Any = None) -> Any:
if time.time() - cls._cache_time < cls.CACHE_TTL and key in cls._cache:
return cls._cache[key]
result = await db.execute(
select(PlatformSetting).where(PlatformSetting.setting_key == key)
)
setting = result.scalar_one_or_none()
if not setting:
return default
value = cls._parse_value(setting.setting_value, setting.data_type)
cls._cache[key] = value
cls._cache_time = time.time()
return value
@classmethod
async def set(cls, key: str, value: Any, db: AsyncSession, user_id: uuid.UUID) -> None:
result = await db.execute(
select(PlatformSetting).where(PlatformSetting.setting_key == key)
)
setting = result.scalar_one_or_none()
str_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value).lower() if isinstance(value, bool) else str(value)
if setting:
setting.setting_value = str_value
setting.updated_by_id = user_id
setting.updated_at = datetime.now(timezone.utc)
else:
setting = PlatformSetting(
setting_key=key,
setting_value=str_value,
data_type=cls._infer_type(value),
updated_by_id=user_id,
)
db.add(setting)
# Invalidate cache
cls._cache.pop(key, None)
cls._cache_time = 0
@classmethod
async def get_all(cls, db: AsyncSession, include_sensitive: bool = False) -> dict[str, Any]:
result = await db.execute(select(PlatformSetting))
settings = result.scalars().all()
out = {}
for s in settings:
if s.is_sensitive and not include_sensitive:
out[s.setting_key] = "***"
else:
out[s.setting_key] = cls._parse_value(s.setting_value, s.data_type)
return out
@staticmethod
def _parse_value(value: Optional[str], data_type: str) -> Any:
if value is None:
return None
if data_type == "boolean":
return value.lower() == "true"
if data_type == "integer":
return int(value)
if data_type == "json":
return json.loads(value)
return value
@staticmethod
def _infer_type(value: Any) -> str:
if isinstance(value, bool):
return "boolean"
if isinstance(value, int):
return "integer"
if isinstance(value, (dict, list)):
return "json"
return "string"