webapp: LAPS clear actually removes the password from session JSON
Previous /imaging/<serial>/laps clear path used update_session() to re-feed state minus laps_password. But update_session MERGES payload into existing state - it cannot delete a key the existing state already has. The laps_password persisted on disk across the "clear" POST, then came back into the page on next reload. Fix: bypass update_session for the clear case. Read the session JSON directly, pop laps_password, write via atomic tempfile-rename. Same write pattern update_session uses for consistency. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ This file is the route surface; most logic lives in ``services/``:
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import tempfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -506,13 +507,29 @@ def imaging_set_laps(serial):
|
|||||||
if not isinstance(pw, str):
|
if not isinstance(pw, str):
|
||||||
return {"ok": False, "error": "password must be string"}, 400
|
return {"ok": False, "error": "password must be string"}, 400
|
||||||
if pw == "":
|
if pw == "":
|
||||||
# Clear by direct read-modify-write since update_session skips empty values.
|
# Clear by direct file write. update_session() merges payload INTO
|
||||||
state = imaging_status.get_session(serial) or {}
|
# existing state and skips empty values, so it cannot remove a key.
|
||||||
|
# Pop the laps_password key directly from the session JSON and
|
||||||
|
# write the result atomically.
|
||||||
|
path = imaging_status._path_for(serial)
|
||||||
|
if os.path.isfile(path):
|
||||||
|
try:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
state = json.load(f)
|
||||||
|
except (json.JSONDecodeError, OSError):
|
||||||
|
state = {}
|
||||||
if "laps_password" in state:
|
if "laps_password" in state:
|
||||||
state.pop("laps_password", None)
|
state.pop("laps_password", None)
|
||||||
# Re-feed everything (minus laps_password) through update_session.
|
state["last_updated"] = imaging_status._now_iso()
|
||||||
state["serial"] = serial
|
fd, tmp = tempfile.mkstemp(dir=config.IMAGING_DIR, prefix=".tmp-", suffix=".json")
|
||||||
imaging_status.update_session(state)
|
try:
|
||||||
|
with os.fdopen(fd, "w") as f:
|
||||||
|
json.dump(state, f, indent=2)
|
||||||
|
os.replace(tmp, path)
|
||||||
|
except Exception:
|
||||||
|
try: os.unlink(tmp)
|
||||||
|
except OSError: pass
|
||||||
|
raise
|
||||||
return {"ok": True, "cleared": True}
|
return {"ok": True, "cleared": True}
|
||||||
imaging_status.update_session({"serial": serial, "laps_password": pw})
|
imaging_status.update_session({"serial": serial, "laps_password": pw})
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|||||||
Reference in New Issue
Block a user