This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 481b2021abc91a633b1e39f9129b6ee6d3c891ba
Author: Dave Brondsema <[email protected]>
AuthorDate: Tue Jun 2 15:09:40 2026 -0400

    [#8607] scoping checks for ForgeChat
---
 ForgeChat/forgechat/main.py                       |  4 +++
 ForgeChat/forgechat/tests/functional/test_root.py | 39 +++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index b09d0b31d..f7976804c 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -142,6 +142,9 @@ def configure(self, channel=None):
 
 class RootController(BaseController):
 
+    def _check_security(self):
+        require_access(c.app, 'read')
+
     @expose()
     def index(self, **kw):
         now = datetime.utcnow()
@@ -183,6 +186,7 @@ def __init__(self, day):
     @expose('jinja:forgechat:templates/chat/day.html')
     def index(self, **kw):
         q = dict(
+            app_config_id=c.app.config._id,
             timestamp={
                 '$gte': datetime.combine(self.day, time.min),
                 '$lte': datetime.combine(self.day, time.max)})
diff --git a/ForgeChat/forgechat/tests/functional/test_root.py 
b/ForgeChat/forgechat/tests/functional/test_root.py
index a11cd761d..3a84f8bf2 100644
--- a/ForgeChat/forgechat/tests/functional/test_root.py
+++ b/ForgeChat/forgechat/tests/functional/test_root.py
@@ -16,9 +16,16 @@
 #       under the License.
 
 import json
+from datetime import datetime
+
+from bson import ObjectId
+from tg import tmpl_context as c
+from ming.odm import ThreadLocalODMSession
 
 from alluratest.controller import TestController
 from allura.tests.decorators import with_tool
+from allura.lib import helpers as h
+from allura import model as M
 
 from forgechat import model as CM
 
@@ -44,3 +51,35 @@ def test_admin_configure(self):
         assert json.loads(self.webflash(resp)) == expected
         ch = CM.ChatChannel.query.get()
         assert ch.channel == 'test channel'
+
+    @with_chat
+    def test_chat_tool_read_required(self):
+        day_url = '/p/test/chat/2020/01/03/'
+        # baseline: anon can read the chat tool on a public project
+        assert self.app.get(day_url, extra_environ={'username': '*anonymous'},
+                            status=200)
+        # remove the chat tool's own 'read' for anon & authenticated (project 
read unchanged)
+        with h.push_context('test', 'chat', neighborhood='Projects'):
+            role = M.ProjectRole.by_name('*anonymous')._id
+            read_permission = M.ACE.allow(role, 'read')
+            c.app.config.acl.remove(read_permission)
+        ThreadLocalODMSession.flush_all()
+        # anon is now blocked from the chat tool even though it still has 
project read
+        self.app.get(day_url, extra_environ={'username': '*anonymous'}, 
status=302)
+        # a project admin still has read
+        assert self.app.get(day_url, status=200)
+
+    @with_chat
+    def test_day_messages_scoped_to_chat_instance(self):
+        ts = datetime(2020, 1, 2, 12, 0)
+        h.set_context('test', 'chat', neighborhood='Projects')
+        # message belonging to THIS chat instance
+        CM.ChatMessage(sender='alice', channel='#a', text='message-alpha', 
timestamp=ts)
+        # message belonging to a DIFFERENT chat instance (other app_config_id, 
same project db)
+        CM.ChatMessage(app_config_id=ObjectId(), sender='bob', channel='#b',
+                       text='message-bravo', timestamp=ts)
+        ThreadLocalODMSession.flush_all()
+        # the day view must show only this instance's message
+        r = self.app.get('/p/test/chat/2020/01/02/')
+        assert 'message-alpha' in r
+        assert 'message-bravo' not in r

Reply via email to