summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/roster.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/roster.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/roster.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/roster.py b/packages/meshbay-node/src/meshbay_node/roster.py
index 226b784..c811016 100644
--- a/packages/meshbay-node/src/meshbay_node/roster.py
+++ b/packages/meshbay-node/src/meshbay_node/roster.py
@@ -100,6 +100,26 @@ CREATE TABLE IF NOT EXISTS members (
PRIMARY KEY (group_id, user_id)
);
+-- Per-group settings the operator changes while the node runs.
+--
+-- Not node.toml: that file is hand-written, full of comments explaining
+-- decisions, and `ops.py` deliberately appends to it rather than round-tripping
+-- it through a TOML writer. A setting toggled from a panel has to take effect
+-- without an edit to the operator's file and without a restart, so it lives
+-- here, where the node already keeps what it decided rather than what it was
+-- configured with.
+--
+-- Absent means default. Nothing writes a row until someone changes something,
+-- so an existing node has the same behaviour it had before this table existed.
+CREATE TABLE IF NOT EXISTS group_settings (
+ group_id TEXT NOT NULL,
+ key TEXT NOT NULL,
+ value TEXT NOT NULL,
+ set_by TEXT NOT NULL DEFAULT '',
+ set_at TEXT NOT NULL DEFAULT '',
+ PRIMARY KEY (group_id, key)
+);
+
CREATE TABLE IF NOT EXISTS invites (
code_hash TEXT PRIMARY KEY,
group_id TEXT NOT NULL,
@@ -518,6 +538,43 @@ class Roster:
# ── Invites ──────────────────────────────────────────────────────────────
+ # ── Group settings ──────────────────────────────────────────────────────
+
+ # Whether members who are not the operator may upload. Default is yes: a
+ # group that nobody may add to is the unusual case, and an existing node
+ # must not change behaviour because a table was added under it.
+ SETTING_MEMBER_UPLOAD = "member_upload"
+
+ async def get_setting(self, group_id: str, key: str,
+ default: str | None = None) -> str | None:
+ async with self._db.execute(
+ "SELECT value FROM group_settings WHERE group_id = ? AND key = ?",
+ (group_id, key)) as cur:
+ row = await cur.fetchone()
+ return row["value"] if row else default
+
+ async def set_setting(self, group_id: str, key: str, value: str,
+ set_by: str = "") -> None:
+ await self._db.execute(
+ "INSERT INTO group_settings (group_id, key, value, set_by, set_at) "
+ "VALUES (?, ?, ?, ?, ?) "
+ "ON CONFLICT(group_id, key) DO UPDATE SET "
+ "value = excluded.value, set_by = excluded.set_by, "
+ "set_at = excluded.set_at",
+ (group_id, key, value, set_by, _now()))
+ await self._db.commit()
+
+ async def member_upload_allowed(self, group_id: str) -> bool:
+ """Whether an ordinary member may upload to this group."""
+ value = await self.get_setting(group_id, self.SETTING_MEMBER_UPLOAD, "1")
+ return value != "0"
+
+ async def set_member_upload(self, group_id: str, allowed: bool,
+ set_by: str = "") -> bool:
+ await self.set_setting(group_id, self.SETTING_MEMBER_UPLOAD,
+ "1" if allowed else "0", set_by)
+ return allowed
+
async def create_invite(
self,
group_id: str,