This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch db/8607b in repository https://gitbox.apache.org/repos/asf/allura.git
commit 68d0a31e9b5155b722a2a93662f66a85069aa2ed Author: Dave Brondsema <[email protected]> AuthorDate: Tue Jun 2 11:38:07 2026 -0400 [#8607] add explicit perm check on project rest controller --- Allura/allura/controllers/rest.py | 3 +++ Allura/allura/tests/functional/test_rest.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py index 7613ac4fb..267855329 100644 --- a/Allura/allura/controllers/rest.py +++ b/Allura/allura/controllers/rest.py @@ -708,6 +708,9 @@ def add_project(self, **kw): class ProjectRestController: + def _check_security(self): + security.require_access(c.project, 'read') + @expose() def _lookup(self, name, *remainder): if not name: diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py index becb5684b..b0c8b3918 100644 --- a/Allura/allura/tests/functional/test_rest.py +++ b/Allura/allura/tests/functional/test_rest.py @@ -26,6 +26,7 @@ import webtest from ming.odm import ThreadLocalODMSession from tg import config +from tg import tmpl_context as c from allura.tests import decorators as td from alluratest.controller import TestRestApiBase @@ -222,6 +223,21 @@ def test_project_data_tools(self): assert 'bugs' in tool_mounts assert 'private-bugs' not in tool_mounts + def test_project_metadata_private_denied_to_anon(self): + # public project: anonymous can read project metadata + DOAP via REST + assert self.app.get('/rest/p/test/', extra_environ={'username': '*anonymous'}, status=200) + # make the project itself private + with h.push_context('test', neighborhood='Projects'): + role = M.ProjectRole.by_name('*anonymous')._id + read_permission = M.ACE.allow(role, 'read') + c.project.acl.remove(read_permission) + ThreadLocalODMSession.flush_all() + # anonymous is now denied the project metadata and member roster (index + doap) + self.app.get('/rest/p/test/', extra_environ={'username': '*anonymous'}, status=401) + self.app.get('/rest/p/test/?doap', extra_environ={'username': '*anonymous'}, status=401) + # an authorized admin can still read it + r = self.api_get('/rest/p/test/', status=200) + def test_neighborhood_has_access_no_params(self): r = self.api_get('/rest/p/has_access', status=404) r = self.api_get('/rest/p/has_access?user=test-admin', status=404)
