From fdc9201660da185428f030211e304e41cd2802a6 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Thu, 4 Jun 2026 20:46:24 +0300 Subject: [PATCH] fix(api): remove broken legacy /system/mqtt/settings route The GET/PUT /api/v1/system/mqtt/settings handlers read cfg.mqtt.*, but the single-broker MQTTConfig block was removed in the multi-broker refactor, so any call raised AttributeError. Brokers are now first-class MQTTSource entities managed via the mqtt.py router, and the frontend no longer calls this endpoint. Remove the dead handlers, the _load_mqtt_settings helper, the now-unused get_config import, and the orphaned MQTTSettings{Request,Response} schemas. --- .../src/ledgrab/api/routes/system_settings.py | 84 +------------------ server/src/ledgrab/api/schemas/system.py | 29 ------- 2 files changed, 1 insertion(+), 112 deletions(-) diff --git a/server/src/ledgrab/api/routes/system_settings.py b/server/src/ledgrab/api/routes/system_settings.py index 172a37d..a3edd9a 100644 --- a/server/src/ledgrab/api/routes/system_settings.py +++ b/server/src/ledgrab/api/routes/system_settings.py @@ -1,4 +1,4 @@ -"""System routes: MQTT, external URL, ADB, logs WebSocket, log level. +"""System routes: external URL, shutdown action, ADB, logs WebSocket, log level. Extracted from system.py to keep files under 800 lines. """ @@ -17,13 +17,10 @@ from ledgrab.api.schemas.system import ( ExternalUrlResponse, LogLevelRequest, LogLevelResponse, - MQTTSettingsRequest, - MQTTSettingsResponse, ShutdownAction, ShutdownActionRequest, ShutdownActionResponse, ) -from ledgrab.config import get_config from ledgrab.storage.database import Database from ledgrab.utils import get_logger @@ -32,85 +29,6 @@ logger = get_logger(__name__) router = APIRouter() -# --------------------------------------------------------------------------- -# MQTT settings -# --------------------------------------------------------------------------- - - -def _load_mqtt_settings(db: Database) -> dict: - """Load MQTT settings: YAML config defaults overridden by DB settings.""" - cfg = get_config() - defaults = { - "enabled": cfg.mqtt.enabled, - "broker_host": cfg.mqtt.broker_host, - "broker_port": cfg.mqtt.broker_port, - "username": cfg.mqtt.username, - "password": cfg.mqtt.password, - "client_id": cfg.mqtt.client_id, - "base_topic": cfg.mqtt.base_topic, - } - overrides = db.get_setting("mqtt") - if overrides: - defaults.update(overrides) - return defaults - - -@router.get( - "/api/v1/system/mqtt/settings", - response_model=MQTTSettingsResponse, - tags=["System"], -) -async def get_mqtt_settings(_: AuthRequired, db: Database = Depends(get_database)): - """Get current MQTT broker settings. Password is masked.""" - s = _load_mqtt_settings(db) - return MQTTSettingsResponse( - enabled=s["enabled"], - broker_host=s["broker_host"], - broker_port=s["broker_port"], - username=s["username"], - password_set=bool(s.get("password")), - client_id=s["client_id"], - base_topic=s["base_topic"], - ) - - -@router.put( - "/api/v1/system/mqtt/settings", - response_model=MQTTSettingsResponse, - tags=["System"], -) -async def update_mqtt_settings( - _: AuthRequired, body: MQTTSettingsRequest, db: Database = Depends(get_database) -): - """Update MQTT broker settings. If password is empty string, the existing password is preserved.""" - current = _load_mqtt_settings(db) - - # If caller sends an empty password, keep the existing one - password = body.password if body.password else current.get("password", "") - - new_settings = { - "enabled": body.enabled, - "broker_host": body.broker_host, - "broker_port": body.broker_port, - "username": body.username, - "password": password, - "client_id": body.client_id, - "base_topic": body.base_topic, - } - db.set_setting("mqtt", new_settings) - logger.info("MQTT settings updated") - - return MQTTSettingsResponse( - enabled=new_settings["enabled"], - broker_host=new_settings["broker_host"], - broker_port=new_settings["broker_port"], - username=new_settings["username"], - password_set=bool(new_settings["password"]), - client_id=new_settings["client_id"], - base_topic=new_settings["base_topic"], - ) - - # --------------------------------------------------------------------------- # External URL setting # --------------------------------------------------------------------------- diff --git a/server/src/ledgrab/api/schemas/system.py b/server/src/ledgrab/api/schemas/system.py index de24d9b..9ac1c87 100644 --- a/server/src/ledgrab/api/schemas/system.py +++ b/server/src/ledgrab/api/schemas/system.py @@ -194,35 +194,6 @@ class BackupListResponse(BaseModel): count: int -# ─── MQTT schemas ────────────────────────────────────────────── - - -class MQTTSettingsResponse(BaseModel): - """MQTT broker settings response (password is masked).""" - - enabled: bool = Field(description="Whether MQTT is enabled") - broker_host: str = Field(description="MQTT broker hostname or IP") - broker_port: int = Field(ge=1, le=65535, description="MQTT broker port") - username: str = Field(description="MQTT username (empty = anonymous)") - password_set: bool = Field(description="Whether a password is configured") - client_id: str = Field(description="MQTT client ID") - base_topic: str = Field(description="Base topic prefix") - - -class MQTTSettingsRequest(BaseModel): - """MQTT broker settings update request.""" - - enabled: bool = Field(description="Whether MQTT is enabled") - broker_host: str = Field(description="MQTT broker hostname or IP") - broker_port: int = Field(ge=1, le=65535, description="MQTT broker port") - username: str = Field(default="", description="MQTT username (empty = anonymous)") - password: str = Field( - default="", description="MQTT password (empty = keep existing if omitted)" - ) - client_id: str = Field(default="ledgrab", description="MQTT client ID") - base_topic: str = Field(default="ledgrab", description="Base topic prefix") - - # ─── External URL schema ───────────────────────────────────────