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 bb89bba9f370db183c4d9aaa78b4929981a2fdb4
Author: Dave Brondsema <[email protected]>
AuthorDate: Mon May 18 13:27:01 2026 -0400

    [#8607] perm checks in markdown_to_html and fix wiki tool check
---
 Allura/allura/controllers/newforge.py           | 14 +++++++---
 Allura/allura/tests/functional/test_newforge.py | 34 ++++++++++++++++++++++---
 Allura/allura/tests/functional/test_root.py     |  3 ++-
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/Allura/allura/controllers/newforge.py 
b/Allura/allura/controllers/newforge.py
index 68351fd3f..ef93940ae 100644
--- a/Allura/allura/controllers/newforge.py
+++ b/Allura/allura/controllers/newforge.py
@@ -23,9 +23,11 @@
 from webob import exc
 
 from tg import app_globals as g
+from tg import tmpl_context as c
 from allura.lib import helpers as h
 from allura.lib import utils
 from allura.lib.exceptions import ForgeError
+from allura.lib.security import require_access
 
 
 class NewForgeController:
@@ -35,16 +37,22 @@ class NewForgeController:
 
     @expose()
     @without_trailing_slash
-    def markdown_to_html(self, markdown, neighborhood=None, project=None, 
app=None):
+    def markdown_to_html(self, markdown, neighborhood, project, app):
         """Convert markdown to html."""
         if neighborhood is None or project is None:
             raise exc.HTTPBadRequest()
         try:
             h.set_context(project, app, neighborhood=neighborhood)
-        except ForgeError:
+        except ForgeError:  # no project or nbhd found
             raise exc.HTTPBadRequest()
 
-        if app == 'wiki':
+        if c.app is None:
+            raise exc.HTTPBadRequest()
+
+        require_access(c.project, 'read')
+        require_access(c.app, 'read')
+
+        if c.app.tool_label.lower() == 'wiki':
             html = g.markdown_wiki.convert(markdown)
         else:
             html = g.markdown.convert(markdown)
diff --git a/Allura/allura/tests/functional/test_newforge.py 
b/Allura/allura/tests/functional/test_newforge.py
index de5432585..c52fbf37d 100644
--- a/Allura/allura/tests/functional/test_newforge.py
+++ b/Allura/allura/tests/functional/test_newforge.py
@@ -17,6 +17,7 @@
 import logging
 from urllib.parse import quote
 
+from ming.odm import ThreadLocalODMSession
 from testfixtures import LogCapture
 
 from allura.tests import TestController
@@ -30,19 +31,46 @@ class TestNewForgeController(TestController):
     def test_markdown_to_html(self):
         n = M.Neighborhood.query.get(name='Projects')
         r = self.app.get(
-            
'/nf/markdown_to_html?markdown=*aaa*bb[wiki:Home]&project=test&app=bugs&neighborhood=%s'
 % n._id, validate_chunk=True)
+            
'/nf/markdown_to_html?markdown=*aaa*bb[wiki:Home]&project=test&app=wiki&neighborhood=%s'
 % n._id, validate_chunk=True)
         assert '<p><em>aaa</em>bb<a class="alink" 
href="/p/test/wiki/Home/">[wiki:Home]</a></p>' in r, r
 
         # this happens to trigger an error
         bad_markdown = '<foo {bar}>'
-        r = 
self.app.get('/nf/markdown_to_html?markdown=%s&project=test&app=bugs&neighborhood=%s'
 %
+        r = 
self.app.get('/nf/markdown_to_html?markdown=%s&project=test&app=wiki&neighborhood=%s'
 %
                          (quote(bad_markdown), n._id))
         r.mustcontain('The markdown supplied could not be parsed correctly.')
         r.mustcontain('<pre>&lt;foo {bar}&gt;</pre>')
 
-        r = 
self.app.get('/nf/markdown_to_html?markdown=*aaa*bb[wiki:Home]&project=test&app=bugs&neighborhood=bogus',
+        r = 
self.app.get('/nf/markdown_to_html?markdown=*aaa*bb[wiki:Home]&project=test&app=wiki&neighborhood=bogus',
                          status=400)
 
+    @td.with_wiki
+    def test_markdown_to_html_private_project(self):
+        # Make the test project private by removing anonymous read access
+        p = M.Project.query.get(shortname='test')
+        p.acl = [ace for ace in p.acl
+                 if not (ace.access == M.ACE.ALLOW
+                         and ace.permission == 'read'
+                         and ace.role_id == M.ProjectRole.anonymous(p)._id)]
+        ThreadLocalODMSession.flush_all()
+
+        n = M.Neighborhood.query.get(name='Projects')
+        # Authenticated user with access should still work
+        r = self.app.get(
+            
'/nf/markdown_to_html?markdown=*hello*&project=test&app=wiki&neighborhood=%s' % 
n._id,
+            extra_environ=dict(username='test-admin'))
+        assert '<p><em>hello</em></p>' in r, r
+
+        # test-user and *anonymous get different errors, but that's ok, 
neither work:
+        self.app.get(
+            
'/nf/markdown_to_html?markdown=*hello*&project=test&app=wiki&neighborhood=%s' % 
n._id,
+            extra_environ=dict(username='test-user'),
+            status=403)
+        self.app.get(
+            
'/nf/markdown_to_html?markdown=*hello*&project=test&app=wiki&neighborhood=%s' % 
n._id,
+            extra_environ=dict(username='*anonymous'),
+            status=302)
+
     def test_markdown_syntax(self):
         with LogCapture(level=logging.INFO) as logs:
             r = self.app.get('/nf/markdown_syntax')
diff --git a/Allura/allura/tests/functional/test_root.py 
b/Allura/allura/tests/functional/test_root.py
index 1c0b8c8f7..b3ca1139b 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -91,11 +91,12 @@ def test_neighborhood(self):
         assert cat_links[0].find('a').get('href') == '/browse/clustering'
         assert cat_links[0].find('a').find('span').string == 'Clustering'
 
+    @td.with_wiki
     def test_validation(self):
         # this is not configured ON currently, so adding an individual test to 
get coverage of the validator itself
         with mock.patch.dict(os.environ, ALLURA_VALIDATION='all'):
             self.app.get('/neighborhood')
-            
self.app.get('/nf/markdown_to_html?markdown=aaa&project=test&app=bugs&neighborhood=%s'
+            
self.app.get('/nf/markdown_to_html?markdown=aaa&project=test&app=wiki&neighborhood=%s'
                          % M.Neighborhood.query.get(name='Projects')._id,
                          validate_chunk=True)
 

Reply via email to