diff options
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/roster.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/roster.py | 57 |
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, |