Fix audit findings in queue fairness and official account lifecycle

This commit is contained in:
Pigway
2026-10-05 00:21:17 +08:00
parent b76af5ada3
commit a180dbc076
12 changed files with 285 additions and 37 deletions
@@ -1,6 +1,7 @@
"""Admin account connection; password transient, session persisted as a secret."""
import json
import logging
import os
import tempfile
import threading
@@ -44,14 +45,32 @@ class Connection:
self.reader, self.path, self.secrets = reader, path, secrets
self.username = ""
self.lock = threading.RLock()
if path.exists():
data = json.loads(path.read_text())
reader.rpc = OfficialRPC(data["token"])
reader._robot_id = data["robot_id"]
self.username = data["username"]
self.secrets.append(data["token"])
try:
if path.exists():
data = json.loads(path.read_text())
if (
not isinstance(data, dict)
or not isinstance(data.get("token"), str)
or not isinstance(data.get("username"), str)
or (
data.get("robot_id") is not None
and (type(data["robot_id"]) is not int or data["robot_id"] <= 0)
)
or "robot_id" not in data
):
raise ValueError()
reader.rpc = OfficialRPC(data["token"])
reader._robot_id = data["robot_id"]
self.username = data["username"]
self.secrets.append(data["token"])
except (OSError, ValueError, KeyError, TypeError):
reader.rpc.disconnect()
reader._robot_id = None
logging.getLogger("frame-flow").warning(
"Official connection configuration unavailable; reconnect required"
)
def _save(self):
def _save(self, token, username, robot_id):
self.path.parent.mkdir(parents=True, exist_ok=True)
with tempfile.NamedTemporaryFile(
mode="w", dir=self.path.parent, delete=False
@@ -60,9 +79,9 @@ class Connection:
try:
json.dump(
{
"token": self.reader.rpc._token,
"username": self.username,
"robot_id": self.reader._robot_id,
"token": token,
"username": username,
"robot_id": robot_id,
},
f,
)
@@ -73,6 +92,31 @@ class Connection:
finally:
temp.unlink(missing_ok=True)
def _commit(self, rpc, username, robot_id):
self._save(rpc._token, username, robot_id)
self.reader.rpc = rpc
self.reader._robot_id = robot_id
self.reader._cached = None
self.username = username
if rpc._token and rpc._token not in self.secrets:
self.secrets.append(rpc._token)
def _query(self, call):
try:
return call()
except FlowError as error:
if error.code == E.OFFICIAL_AUTH_REQUIRED:
self.reader.rpc.disconnect()
self.reader._cached = None
self.reader._robot_id = None
try:
self._save("", self.username, None)
except OSError:
logging.getLogger("frame-flow").warning(
"Expired official connection could not be persisted"
)
raise
def _devices(self, rpc):
if self.reader.mock:
return [
@@ -85,7 +129,9 @@ class Connection:
)
]
try:
data = rpc.devices()["data"]
data = (
self._query(rpc.devices) if rpc is self.reader.rpc else rpc.devices()
)["data"]
return [
OfficialDevice(
id=row["id"],
@@ -119,12 +165,7 @@ class Connection:
if not self.reader.mock:
rpc.login(username, password)
devices = self._devices(rpc)
self.reader.rpc = rpc
self.reader._robot_id = None
self.reader._cached = None
self.username = username
self.secrets.append(rpc._token)
self._save()
self._commit(rpc, username, None)
return ConnectionState(
authorized=True,
username=username,
@@ -143,20 +184,14 @@ class Connection:
raise FlowError(
E.DEVICE_NOT_FOUND, "Official device not in this account", 404
)
self.reader._robot_id = robot_id
self.reader._cached = None
self._save()
self._commit(self.reader.rpc, self.username, robot_id)
return self.state()
def disconnect(self):
with self.lock:
self.reader.rpc.disconnect()
self.reader._robot_id = None
self.reader._cached = None
self.username = ""
self._save()
self._commit(OfficialRPC(), "", None)
return self.state()
def widgets(self):
with self.lock:
return self.reader.read()
return self._query(self.reader.read)