feat: Add local system override with 24h timeout support
This commit is contained in:
@@ -94,6 +94,11 @@ class MQTTHandler:
|
||||
"last_seen": now.isoformat(),
|
||||
"assigned_system_id": None,
|
||||
"approval_status": "pending",
|
||||
"node_type": payload.get("node_type", "fixed"),
|
||||
"enforce_override_timeout": payload.get("enforce_override_timeout", True),
|
||||
"is_overridden": False,
|
||||
"override_system_id": None,
|
||||
"override_timeout_at": None,
|
||||
}
|
||||
await fstore.doc_set("nodes", node_id, doc, merge=False)
|
||||
logger.info(f"New node registered: {node_id} — pending admin approval.")
|
||||
@@ -111,6 +116,35 @@ class MQTTHandler:
|
||||
elif existing.get("approval_status") == "approved":
|
||||
# Approved but not yet configured — restore reachable status after reboot
|
||||
updates["status"] = "unconfigured"
|
||||
|
||||
node_type = payload.get("node_type", existing.get("node_type", "fixed"))
|
||||
enforce_timeout = payload.get("enforce_override_timeout", existing.get("enforce_override_timeout", True))
|
||||
is_overridden = payload.get("is_overridden", False)
|
||||
override_system_id = payload.get("override_system_id")
|
||||
|
||||
updates["node_type"] = node_type
|
||||
updates["enforce_override_timeout"] = enforce_timeout
|
||||
|
||||
if node_type == "portable":
|
||||
updates["is_overridden"] = False
|
||||
updates["override_system_id"] = None
|
||||
updates["override_timeout_at"] = None
|
||||
else:
|
||||
updates["is_overridden"] = is_overridden
|
||||
updates["override_system_id"] = override_system_id
|
||||
|
||||
if is_overridden:
|
||||
existing_timeout = existing.get("override_timeout_at")
|
||||
existing_override_id = existing.get("override_system_id")
|
||||
if enforce_timeout:
|
||||
if not existing_timeout or existing_override_id != override_system_id:
|
||||
from datetime import timedelta
|
||||
updates["override_timeout_at"] = (now + timedelta(hours=24)).isoformat()
|
||||
else:
|
||||
updates["override_timeout_at"] = None
|
||||
else:
|
||||
updates["override_timeout_at"] = None
|
||||
|
||||
await fstore.doc_update("nodes", node_id, updates)
|
||||
|
||||
# NOTE: discord_connected in checkins is informational only — do NOT release the
|
||||
|
||||
@@ -55,3 +55,35 @@ async def _sweep():
|
||||
logger.info(f"Node {node_id} marked offline (last seen: {last_seen.isoformat()})")
|
||||
from app.routers.tokens import release_token
|
||||
await release_token(node_id)
|
||||
continue
|
||||
|
||||
# Check for expired system overrides (only for fixed nodes with timeout enforced)
|
||||
override_timeout_raw = node.get("override_timeout_at")
|
||||
enforce_timeout = node.get("enforce_override_timeout", True)
|
||||
node_type = node.get("node_type", "fixed")
|
||||
|
||||
if override_timeout_raw and enforce_timeout and node_type != "portable":
|
||||
if isinstance(override_timeout_raw, str):
|
||||
override_timeout = datetime.fromisoformat(override_timeout_raw)
|
||||
else:
|
||||
override_timeout = override_timeout_raw
|
||||
if override_timeout.tzinfo is None:
|
||||
override_timeout = override_timeout.replace(tzinfo=timezone.utc)
|
||||
|
||||
if datetime.now(timezone.utc) > override_timeout:
|
||||
node_id = node.get("node_id")
|
||||
assigned_system_id = node.get("assigned_system_id")
|
||||
logger.info(f"Node {node_id} override has expired. Reverting to system {assigned_system_id}.")
|
||||
|
||||
# Push the original assigned config if it exists
|
||||
if assigned_system_id:
|
||||
system_doc = await fstore.doc_get("systems", assigned_system_id)
|
||||
if system_doc:
|
||||
from app.internal.mqtt_handler import mqtt_handler
|
||||
mqtt_handler.push_config(node_id, system_doc)
|
||||
|
||||
await fstore.doc_update("nodes", node_id, {
|
||||
"is_overridden": False,
|
||||
"override_system_id": None,
|
||||
"override_timeout_at": None,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user