From a5c3e36fce96194f14c0fb876631723828b9949d Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Tue, 21 Apr 2026 19:59:40 -0400 Subject: [PATCH] fix: Namespace.moderators returned all members; owners now imply mod MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit moderators property returned self.enabled_users (every enabled member), so every user who had ever posted got moderator powers: spam approve/deny, edit/delete other users' comments, moderator Slack notifications. Bug was universal across all namespaces — any site where users post was affected. Fix: moderators now returns only users with role='moderator'. Owners now implicitly pass is_moderator() checks, since NamespaceUser is single-role per user per namespace; this keeps owners functional without needing a data migration. --- remarkbox/models/namespace.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/remarkbox/models/namespace.py b/remarkbox/models/namespace.py index e5d0127..1a33d8b 100644 --- a/remarkbox/models/namespace.py +++ b/remarkbox/models/namespace.py @@ -272,7 +272,7 @@ class Namespace(RBase, Base): @property def moderators(self): """Return a list of moderator role User objects.""" - return self.enabled_users + return self.roles.get("moderator", []) @property def visible_roots(self): @@ -382,12 +382,15 @@ class Namespace(RBase, Base): """Return True if given user moderates this namespace, else False. Superusers are treated as moderators on every namespace. + Owners are implicitly moderators. """ if user and user.authenticated: if getattr(user, "is_superuser", False): return True if user in self.moderators: return True + if user in self.owners: + return True return False def can_alter_node(self, node, user):