This is an automated email from the ASF dual-hosted git repository. brondsem pushed a commit to branch db/8556-breaking-removal in repository https://gitbox.apache.org/repos/asf/allura.git
commit 11902a6d366c78fbe6e7e28638293aff9bdb421f Author: Dave Brondsema <dbronds...@slashdotmedia.com> AuthorDate: Wed Apr 3 14:00:52 2024 -0400 [#8556] remove TruthyCallable and predicate stuff used by has_access --- Allura/allura/controllers/auth.py | 6 +++--- Allura/allura/controllers/basetest_project_root.py | 8 +++---- Allura/allura/controllers/rest.py | 2 +- Allura/allura/lib/security.py | 23 +++++++------------- Allura/allura/lib/utils.py | 25 ---------------------- Allura/allura/tests/test_plugin.py | 1 - Allura/allura/tests/test_utils.py | 21 ------------------ ForgeTracker/forgetracker/tracker_main.py | 2 +- .../033-change-comment-anon-permissions.py | 2 +- 9 files changed, 18 insertions(+), 72 deletions(-) diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py index fab1757e8..628801648 100644 --- a/Allura/allura/controllers/auth.py +++ b/Allura/allura/controllers/auth.py @@ -513,9 +513,9 @@ class AuthController(BaseController): log.info("Can't find repo at %s on repo_path %s", rest[0], repo_path) return disallow - return dict(allow_read=bool(has_access(c.app, 'read', user)), - allow_write=bool(has_access(c.app, 'write', user)), - allow_create=bool(has_access(c.app, 'create', user))) + return dict(allow_read=has_access(c.app, 'read', user), + allow_write=has_access(c.app, 'write', user), + allow_create=has_access(c.app, 'create', user)) @expose('jinja:allura:templates/pwd_expired.html') @without_trailing_slash diff --git a/Allura/allura/controllers/basetest_project_root.py b/Allura/allura/controllers/basetest_project_root.py index 90dc7e88c..341bb5bca 100644 --- a/Allura/allura/controllers/basetest_project_root.py +++ b/Allura/allura/controllers/basetest_project_root.py @@ -165,7 +165,7 @@ class SecurityTest: @expose() def forbidden(self): - require(lambda: False, 'Never allowed') + require(False, 'Never allowed') return '' @expose() @@ -180,10 +180,10 @@ class SecurityTest: @expose() def needs_project_access_ok(self): - pred = has_access(c.project, 'read') - if not pred(): + ok = has_access(c.project, 'read') + if not ok: log.info('Inside needs_project_access, c.user = %s' % c.user) - require(pred) + require(ok) return '' @expose() diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py index 0f29c1676..d0ca8476d 100644 --- a/Allura/allura/controllers/rest.py +++ b/Allura/allura/controllers/rest.py @@ -481,7 +481,7 @@ def rest_has_access(obj, user, perm): resp = {'result': False} user = M.User.by_username(user) if user: - resp['result'] = bool(security.has_access(obj, perm, user=user)) + resp['result'] = security.has_access(obj, perm, user=user) return resp diff --git a/Allura/allura/lib/security.py b/Allura/allura/lib/security.py index 53a675f55..a762af965 100644 --- a/Allura/allura/lib/security.py +++ b/Allura/allura/lib/security.py @@ -33,8 +33,6 @@ from itertools import chain from ming.utils import LazyProperty import tg -from allura.lib.utils import TruthyCallable - if typing.TYPE_CHECKING: from allura.model import M @@ -305,7 +303,7 @@ def debug_obj(obj) -> str: return str(obj) -def has_access(obj, permission: str, user: M.User | None = None, project: M.Project | None = None) -> TruthyCallable: +def has_access(obj, permission: str, user: M.User | None = None, project: M.Project | None = None, roles=None) -> bool: '''Return whether the given user has the permission name on the given object. - First, all the roles for a user in the given project context are computed. @@ -348,7 +346,7 @@ def has_access(obj, permission: str, user: M.User | None = None, project: M.Proj DEBUG = False - def predicate(obj=obj, user=user, project=project, roles=None) -> bool: + if True: if obj is None: if DEBUG: log.debug(f'{user} denied {permission} on {debug_obj(obj)} ({debug_obj(project)})') @@ -396,19 +394,16 @@ def has_access(obj, permission: str, user: M.User | None = None, project: M.Proj chainable_roles.append(role) parent = obj.parent_security_context() if parent and chainable_roles: - result = has_access(parent, permission, user=user, project=project)( - roles=tuple(chainable_roles)) + result = has_access(parent, permission, user=user, project=project, roles=tuple(chainable_roles)) elif not isinstance(obj, M.Neighborhood): result = has_access(project.neighborhood, 'admin', user=user) if not (result or isinstance(obj, M.Project)): result = has_access(project, 'admin', user=user) else: result = False - result = bool(result) if DEBUG: log.debug(f"{user.username} '{permission}' {result} from parent(s) on {debug_obj(obj)} ({debug_obj(project)})") return result - return TruthyCallable(predicate) def all_allowed(obj, user_or_role=None, project=None): @@ -488,17 +483,15 @@ def is_allowed_by_role(obj, permission, role_name, project): return permission in all_allowed(obj, role, project) -def require(predicate, message=None): +def require(allowed, message=None): ''' - Example: ``require(has_access(c.app, 'read'))`` - - :param callable predicate: truth function to call + :param bool allowed: :param str message: message to show upon failure :raises: HTTPForbidden or HTTPUnauthorized ''' from allura import model as M - if predicate(): + if allowed: return if not message: message = """You don't have permission to do that. @@ -513,8 +506,8 @@ def require(predicate, message=None): def require_access(obj, permission, **kwargs): if obj is not None: - predicate = has_access(obj, permission, **kwargs) - return require(predicate, message='%s access required' % permission.capitalize()) + allowed = has_access(obj, permission, **kwargs) + return require(allowed, message='%s access required' % permission.capitalize()) else: raise exc.HTTPForbidden( detail="Could not verify permissions for this page.") diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py index de33f559b..b6edcd610 100644 --- a/Allura/allura/lib/utils.py +++ b/Allura/allura/lib/utils.py @@ -396,31 +396,6 @@ class AntiSpam: return before_validate(antispam_hook) -class TruthyCallable: - ''' - Wraps a callable to make it truthy in a boolean context. - - Assumes the callable returns a truthy value and can be called with no args. - ''' - - def __init__(self, callable): - self.callable = callable - - def __call__(self, *args, **kw): - return self.callable(*args, **kw) - - def __bool__(self): - return self.callable() - - def __eq__(self, other): - if other is True and bool(self): - return True - elif other is False and not bool(self): - return True - else: - return NotImplemented - - class TransformedDict(MutableMapping): """ diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py index c57e9e4a4..085e3a143 100644 --- a/Allura/allura/tests/test_plugin.py +++ b/Allura/allura/tests/test_plugin.py @@ -30,7 +30,6 @@ from allura import model as M from allura.lib import plugin from allura.lib import phone from allura.lib import helpers as h -from allura.lib.utils import TruthyCallable from allura.lib.plugin import ProjectRegistrationProvider from allura.lib.plugin import ThemeProvider from allura.lib.exceptions import ProjectConflict, ProjectShortnameInvalid diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py index 131e9bf95..57b1b830b 100644 --- a/Allura/allura/tests/test_utils.py +++ b/Allura/allura/tests/test_utils.py @@ -169,27 +169,6 @@ class TestAntispam(unittest.TestCase): return encrypted_form -class TestTruthyCallable(unittest.TestCase): - - def test_everything(self): - def wrapper_func(bool_flag): - def predicate(bool_flag=bool_flag): - return bool_flag - return utils.TruthyCallable(predicate) - true_predicate = wrapper_func(True) - false_predicate = wrapper_func(False) - assert true_predicate(True) is True - assert false_predicate(False) is False - assert true_predicate() is True - assert false_predicate() is False - assert bool(true_predicate) is True - assert bool(false_predicate) is False - - t, f = True, False # use variables because '== True' would generate warnings, and we do want '==' not 'is' - assert true_predicate == t - assert false_predicate == f - - class TestCaseInsensitiveDict(unittest.TestCase): def test_everything(self): diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py index 31f3bed10..b1e8e7ee5 100644 --- a/ForgeTracker/forgetracker/tracker_main.py +++ b/ForgeTracker/forgetracker/tracker_main.py @@ -1183,7 +1183,7 @@ class BinController(BaseController, AdminControllerMixin): if bin is None: bin = TM.Bin(app_config_id=self.app.config._id, summary='') new_bin = bin - require(lambda: bin.app_config_id == self.app.config._id) + require(bin.app_config_id == self.app.config._id) bin.summary = bin_form['summary'] bin.terms = bin_form['terms'] try: diff --git a/scripts/migrations/033-change-comment-anon-permissions.py b/scripts/migrations/033-change-comment-anon-permissions.py index d3189c23a..8fc3d8abd 100644 --- a/scripts/migrations/033-change-comment-anon-permissions.py +++ b/scripts/migrations/033-change-comment-anon-permissions.py @@ -47,7 +47,7 @@ def main(): for chunk in utils.chunked_find(ForumPost, {'app_config_id':tool._id}): for p in chunk: - has_access = bool(security.has_access(p, 'moderate', M.User.anonymous())) + has_access = security.has_access(p, 'moderate', M.User.anonymous()) if has_access: anon_role_id = None