Cache user permissions upon "new request" event

this avoids a ton of (often redundant) SQL queries when checking permissions
This commit is contained in:
Lance Edgar 2018-10-17 12:50:02 -05:00
parent 0ed3429cf7
commit 79e71ec4ab

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2017 Lance Edgar # Copyright © 2010-2018 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -32,7 +32,7 @@ import datetime
import rattail import rattail
from rattail.db import model from rattail.db import model
from rattail.db.auth import has_permission from rattail.db.auth import cache_permissions
from pyramid import threadlocal from pyramid import threadlocal
@ -41,34 +41,43 @@ from tailbone import helpers
from tailbone.db import Session 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. Identify the current user, and cache their current permissions. Also adds
the ``rattail_config`` attribute to the request.
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.
A global Rattail ``config`` should already be present within the Pyramid A global Rattail ``config`` should already be present within the Pyramid
application registry's settings, which would normally be accessed via:: application registry's settings, which would normally be accessed via::
request.registry.settings['rattail_config'] 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:: directly accessible, a la::
request.rattail_config request.rattail_config
.. note:: .. note::
All this of course assumes that a Rattail ``config`` object *has* in This of course assumes that a Rattail ``config`` object *has* in fact
fact already been placed in the application registry settings. If this already been placed in the application registry settings. If this is
is not the case, this function will do nothing. not the case, this function will do nothing.
""" """
request = event.request request = event.request
rattail_config = request.registry.settings.get('rattail_config') rattail_config = request.registry.settings.get('rattail_config')
if rattail_config: if rattail_config:
request.rattail_config = 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): def before_render(event):
""" """
@ -126,18 +135,8 @@ def context_found(event):
request = event.request 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): def has_perm(name):
if has_permission(Session(), request.user, name): if name in request.tailbone_cached_permissions:
return True return True
return request.is_root return request.is_root
request.has_perm = has_perm request.has_perm = has_perm
@ -175,6 +174,6 @@ def context_found(event):
def includeme(config): 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(before_render, 'pyramid.events.BeforeRender')
config.add_subscriber(context_found, 'pyramid.events.ContextFound') config.add_subscriber(context_found, 'pyramid.events.ContextFound')