From e3942ce65e231f01e20b101189d3441615d5b16d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 14 Aug 2024 21:20:00 -0500 Subject: [PATCH] feat: add permission checks for menus, view routes --- src/wuttaweb/menus.py | 5 +- src/wuttaweb/subscribers.py | 65 +++++++++++++-- src/wuttaweb/templates/base.mako | 5 +- src/wuttaweb/views/common.py | 46 ++++++++++- src/wuttaweb/views/master.py | 87 +++++++++++++++++--- src/wuttaweb/views/roles.py | 31 +++++++ tests/test_menus.py | 33 +++++--- tests/test_subscribers.py | 133 ++++++++++++++++++++++++++++++- tests/util.py | 5 +- tests/views/test_master.py | 131 ++++++++++++++++++++++++++++++ tests/views/test_roles.py | 36 +++++++++ 11 files changed, 537 insertions(+), 40 deletions(-) diff --git a/src/wuttaweb/menus.py b/src/wuttaweb/menus.py index fc4581a..84d5534 100644 --- a/src/wuttaweb/menus.py +++ b/src/wuttaweb/menus.py @@ -272,9 +272,8 @@ class MenuHandler(GenericHandler): current user. """ perm = item.get('perm') - # TODO - # if perm: - # return request.has_perm(perm) + if perm: + return request.has_perm(perm) return True def _mark_allowed(self, request, menus): diff --git a/src/wuttaweb/subscribers.py b/src/wuttaweb/subscribers.py index 2202059..eed4efe 100644 --- a/src/wuttaweb/subscribers.py +++ b/src/wuttaweb/subscribers.py @@ -139,6 +139,16 @@ def new_request_set_user( pyramid_config.add_subscriber('wuttaweb.subscribers.new_request_set_user', 'pyramid.events.NewRequest') + You may wish to "supplement" this hook by registering your own + custom hook and then invoking this one as needed. You can then + pass certain params to override only parts of the logic: + + :param user_getter: Optional getter function to retrieve the user + from database, instead of :func:`default_user_getter()`. + + :param db_session: Optional :term:`db session` to use, + instead of :class:`wuttaweb.db.Session`. + This will add to the request object: .. attribute:: request.user @@ -158,19 +168,36 @@ def new_request_set_user( privileges. This is only possible if :attr:`request.is_admin` is also true. - You may wish to "supplement" this hook by registering your own - custom hook and then invoking this one as needed. You can then - pass certain params to override only parts of the logic: + .. attribute:: request.user_permissions - :param user_getter: Optional getter function to retrieve the user - from database, instead of :func:`default_user_getter()`. + The ``set`` of permission names which are granted to the + current user. + + This set is obtained by calling + :meth:`~wuttjamaican:wuttjamaican.auth.AuthHandler.get_permissions()`. + + .. function:: request.has_perm(name) + + Shortcut to check if current user has the given permission:: + + if not request.has_perm('users.edit'): + raise self.forbidden() + + .. function:: request.has_any_perm(*names) + + Shortcut to check if current user has any of the given + permissions:: + + if request.has_any_perm('users.list', 'users.view'): + return "can either list or view" + else: + raise self.forbidden() - :param db_session: Optional :term:`db session` to use, - instead of :class:`wuttaweb.db.Session`. """ request = event.request config = request.registry.settings['wutta_config'] app = config.get_app() + auth = app.get_auth_handler() # request.user if db_session: @@ -179,7 +206,6 @@ def new_request_set_user( # request.is_admin def is_admin(request): - auth = app.get_auth_handler() return auth.user_is_admin(request.user) request.set_property(is_admin, reify=True) @@ -191,6 +217,29 @@ def new_request_set_user( return False request.set_property(is_root, reify=True) + # request.user_permissions + def user_permissions(request): + session = db_session or Session() + return auth.get_permissions(session, request.user) + request.set_property(user_permissions, reify=True) + + # request.has_perm() + def has_perm(name): + if request.is_root: + return True + if name in request.user_permissions: + return True + return False + request.has_perm = has_perm + + # request.has_any_perm() + def has_any_perm(*names): + for name in names: + if request.has_perm(name): + return True + return False + request.has_any_perm = has_any_perm + def before_render(event): """ diff --git a/src/wuttaweb/templates/base.mako b/src/wuttaweb/templates/base.mako index eab8bf0..aaec2c7 100644 --- a/src/wuttaweb/templates/base.mako +++ b/src/wuttaweb/templates/base.mako @@ -222,7 +222,7 @@ % else:

${index_title}

% endif - % if master and master.creatable and not master.creating: + % if master and master.creatable and not master.creating and master.has_perm('create'): - ## TODO - % if master and master.configurable and not master.configuring: + % if master and master.configurable and not master.configuring and master.has_perm('configure'):