From 79e71ec4abe932f1247cf796a3a4f72120afea2f Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 17 Oct 2018 12:50:02 -0500 Subject: [PATCH] Cache user permissions upon "new request" event this avoids a ton of (often redundant) SQL queries when checking permissions --- tailbone/subscribers.py | 47 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/tailbone/subscribers.py b/tailbone/subscribers.py index 34d55043..f6e83ad4 100644 --- a/tailbone/subscribers.py +++ b/tailbone/subscribers.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2017 Lance Edgar +# Copyright © 2010-2018 Lance Edgar # # This file is part of Rattail. # @@ -32,7 +32,7 @@ import datetime import rattail from rattail.db import model -from rattail.db.auth import has_permission +from rattail.db.auth import cache_permissions from pyramid import threadlocal @@ -41,34 +41,43 @@ from tailbone import helpers from tailbone.db import Session -def add_rattail_config_attribute_to_request(event): +def new_request(event): """ - Add a ``rattail_config`` attribute to a request object. - - This function is really just a matter of convenience, but it should help to - make other code more terse (example below). It is designed to act as a - subscriber to the Pyramid ``NewRequest`` event. + Identify the current user, and cache their current permissions. Also adds + the ``rattail_config`` attribute to the request. A global Rattail ``config`` should already be present within the Pyramid application registry's settings, which would normally be accessed via:: request.registry.settings['rattail_config'] - This function merely "promotes" this config object so that it is more + This function merely "promotes" that config object so that it is more directly accessible, a la:: request.rattail_config .. note:: - All this of course assumes that a Rattail ``config`` object *has* in - fact already been placed in the application registry settings. If this - is not the case, this function will do nothing. + This of course assumes that a Rattail ``config`` object *has* in fact + already been placed in the application registry settings. If this is + not the case, this function will do nothing. """ request = event.request rattail_config = request.registry.settings.get('rattail_config') if rattail_config: request.rattail_config = rattail_config + request.user = None + uuid = request.authenticated_userid + if uuid: + request.user = Session.query(model.User).get(uuid) + if request.user: + Session().set_continuum_user(request.user) + + request.is_admin = bool(request.user) and request.user.is_admin() + request.is_root = request.is_admin and request.session.get('is_root', False) + + request.tailbone_cached_permissions = cache_permissions(Session(), request.user) + def before_render(event): """ @@ -126,18 +135,8 @@ def context_found(event): request = event.request - request.user = None - uuid = request.authenticated_userid - if uuid: - request.user = Session.query(model.User).get(uuid) - if request.user: - Session().set_continuum_user(request.user) - - request.is_admin = bool(request.user) and request.user.is_admin() - request.is_root = request.is_admin and request.session.get('is_root', False) - def has_perm(name): - if has_permission(Session(), request.user, name): + if name in request.tailbone_cached_permissions: return True return request.is_root request.has_perm = has_perm @@ -175,6 +174,6 @@ def context_found(event): def includeme(config): - config.add_subscriber(add_rattail_config_attribute_to_request, 'pyramid.events.NewRequest') + config.add_subscriber(new_request, 'pyramid.events.NewRequest') config.add_subscriber(before_render, 'pyramid.events.BeforeRender') config.add_subscriber(context_found, 'pyramid.events.ContextFound')