浏览代码

API configurazione GUI

master
父节点
当前提交
52cb4b88ea
共有 5 个文件被更改,包括 149 次插入1 次删除
  1. +1
    -0
      app.py
  2. +1
    -0
      logica_reslevis/config.py
  3. +88
    -0
      logica_reslevis/user_preferences.py
  4. +39
    -0
      routes/reslevis.py
  5. +20
    -1
      schemas/reslevis.py

+ 1
- 0
app.py 查看文件

@@ -154,6 +154,7 @@ async def local_then_core(request: Request, call_next):
internal_core_proxy_paths = {
"/reslevis/updateAlarm",
"/reslevis/updateCoreSettings",
"/reslevis/updateUserPreferences",
}
# only proxy CRUD for Reslevis (change prefix or methods if needed)
if (


+ 1
- 0
logica_reslevis/config.py 查看文件

@@ -27,4 +27,5 @@ TRACK_JSON_PATH = DATA_DIR / "tracks.json"
TRACKER_ZONE_JSON_PATH = DATA_DIR / "tracker_zone.json"
SETTING_JSON_PATH = DATA_DIR / "settings.json"
GUI_CONFIG_JSON_PATH = DATA_DIR / "gui_config.json"
USER_PREFERENCES_JSON_PATH = DATA_DIR / "user_preferences.json"


+ 88
- 0
logica_reslevis/user_preferences.py 查看文件

@@ -0,0 +1,88 @@
import json
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional
from uuid import NAMESPACE_URL, uuid5

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import UserPreferencesUpdateItem
from .config import USER_PREFERENCES_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str


def _model_to_dict(model: Any) -> Dict[str, Any]:
if hasattr(model, "model_dump"):
return model.model_dump(exclude_unset=True, exclude_none=True)
return model.dict(exclude_unset=True, exclude_none=True)


class UserPreferencesJsonRepository:
def __init__(self, json_path: str = USER_PREFERENCES_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def _index_by_uid(self, rows: List[Dict[str, Any]], uid: str) -> Optional[int]:
target = _norm_str(uid)
for i, row in enumerate(rows):
if _norm_str(row.get("uid")) == target:
return i
return None

def _default_for_uid(self, uid: str) -> Dict[str, Any]:
return {
"id": str(uuid5(NAMESPACE_URL, f"reslevis:user-preferences:{uid}")),
"uid": uid,
"language": "it",
"tables": {},
"updated_at": None,
}

def get(self, uid: str) -> Dict[str, Any]:
rows = self._read_all()
idx = self._index_by_uid(rows, uid)
if idx is None:
return self._default_for_uid(uid)

obj = self._default_for_uid(uid)
obj.update(rows[idx])
obj["uid"] = uid
obj["tables"] = obj.get("tables") or {}
obj["language"] = obj.get("language") or "it"
return obj

def update(self, uid: str, item: UserPreferencesUpdateItem) -> Dict[str, Any]:
rows = self._read_all()
idx = self._index_by_uid(rows, uid)
current = self._default_for_uid(uid) if idx is None else self.get(uid)
payload = jsonable_encoder(_model_to_dict(item))

if "language" in payload and payload["language"] is not None:
current["language"] = payload["language"]

if "tables" in payload and payload["tables"] is not None:
tables = current.get("tables") or {}
for table_name, table_preferences in payload["tables"].items():
tables[table_name] = table_preferences or {"hiddenColumns": {}}
current["tables"] = tables

current["uid"] = uid
current["updated_at"] = datetime.now(timezone.utc).isoformat()

if idx is None:
rows.append(current)
else:
rows[idx] = current
self._write_all(rows)
return current

+ 39
- 0
routes/reslevis.py 查看文件

@@ -24,6 +24,8 @@ from schemas.reslevis import (
TrackerZoneItem,
SettingItem,
GuiConfigItem,
UserPreferencesItem,
UserPreferencesUpdateItem,
CoreSettingsItem,
CoreSettingsUpdateItem,
)
@@ -37,6 +39,7 @@ from logica_reslevis.tracker import TrackerJsonRepository
from logica_reslevis.operator import OperatorJsonRepository
from logica_reslevis.setting import SettingJsonRepository
from logica_reslevis.gui_config import GuiConfigJsonRepository
from logica_reslevis.user_preferences import UserPreferencesJsonRepository
from logica_reslevis.subject import SubjectJsonRepository
from logica_reslevis.alarm import AlarmJsonRepository
from logica_reslevis.track import TrackJsonRepository
@@ -94,6 +97,7 @@ track_repo = TrackJsonRepository()
tracker_zone_repo = TrackerZoneJsonRepository()
setting_repo = SettingJsonRepository()
gui_config_repo = GuiConfigJsonRepository()
user_preferences_repo = UserPreferencesJsonRepository()

def _none_if_empty(v):
return None if v in ("", None, 0, "0") else v
@@ -155,6 +159,18 @@ def _normalize_zone(row: dict) -> dict:
row["groups"] = _uuid_list(row.get("groups"))
return row


def _uid_from_claims(claims: dict) -> str:
uid = (
claims.get("preferred_username")
or claims.get("username")
or claims.get("email")
or claims.get("sub")
)
if not uid:
raise HTTPException(status_code=401, detail="User identity not found in token")
return str(uid)

CORE_GET_SYNC = {
"/reslevis/getGateways": (gateway_repo, _normalize_gateway),
"/reslevis/getZones": (zone_repo, _normalize_zone),
@@ -604,6 +620,29 @@ def getGuiConfigs():
return gui_config_repo.list()


@router.get(
"/getUserPreferences",
response_model=UserPreferencesItem,
tags=["Reslevis"],
)
def getUserPreferences(current_user: dict = Depends(get_current_user)):
uid = _uid_from_claims(current_user)
return user_preferences_repo.get(uid)


@router.put(
"/updateUserPreferences",
response_model=UserPreferencesItem,
tags=["Reslevis"],
)
def updateUserPreferences(
item: UserPreferencesUpdateItem,
current_user: dict = Depends(get_current_user),
):
uid = _uid_from_claims(current_user)
return user_preferences_repo.update(uid, item)


@router.post("/postGuiConfig", tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def postGuiConfig(item: GuiConfigItem):
gui_config_repo.add(item)


+ 20
- 1
schemas/reslevis.py 查看文件

@@ -1,9 +1,10 @@
from pydantic import BaseModel
from pydantic import BaseModel, Field
from typing import Optional
from uuid import UUID
from typing import Optional, Union, Literal
from typing import List
from typing import Tuple
from typing import Dict

class BuildingItem(BaseModel):
id: UUID
@@ -113,6 +114,24 @@ class GuiConfigItem(BaseModel):
role: Optional[Literal["developer", "administrator", "user"]] = None
debug: Optional[bool] = None


class TablePreferenceItem(BaseModel):
hiddenColumns: Dict[str, bool] = Field(default_factory=dict)


class UserPreferencesItem(BaseModel):
id: Optional[UUID] = None
uid: str
language: Literal["it", "en"] = "it"
tables: Dict[str, TablePreferenceItem] = Field(default_factory=dict)
updated_at: Optional[str] = None


class UserPreferencesUpdateItem(BaseModel):
language: Optional[Literal["it", "en"]] = None
tables: Optional[Dict[str, TablePreferenceItem]] = None


class OperatorItem(BaseModel):
id: UUID
name: str


正在加载...
取消
保存