summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@proxience.com>2015-12-08 02:26:03 +0100
committerÉtienne Loks <etienne.loks@proxience.com>2015-12-08 02:26:03 +0100
commit544cb74d6d49deb73ace116df02716adc5b6a464 (patch)
tree5ea46df7c455810a61d3e278a80d6259c645a286
parent35a972ad5de7aa8191da0463457255b868258ec9 (diff)
downloadIshtar-544cb74d6d49deb73ace116df02716adc5b6a464.tar.bz2
Ishtar-544cb74d6d49deb73ace116df02716adc5b6a464.zip
Use cache for faster rights checking
-rw-r--r--archaeological_files/models.py2
-rw-r--r--archaeological_files/views.py3
-rw-r--r--archaeological_operations/views.py26
-rw-r--r--archaeological_warehouse/views.py12
-rw-r--r--example_project/settings.py1
-rw-r--r--ishtar_common/backend.py18
-rw-r--r--ishtar_common/context_processors.py3
-rw-r--r--ishtar_common/menu_base.py34
-rw-r--r--ishtar_common/menus.py17
-rw-r--r--ishtar_common/models.py48
-rw-r--r--ishtar_common/views.py30
-rw-r--r--ishtar_common/wizards.py4
12 files changed, 123 insertions, 75 deletions
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index 93cbdff13..16cd6df65 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -46,7 +46,7 @@ class FileType(GeneralType):
def is_preventive(cls, file_type_id, key=''):
key = key or 'preventive'
try:
- preventive = FileType.objects.get(txt_idx=key).pk
+ preventive = FileType.get_cache(key).pk
return file_type_id == preventive
except FileType.DoesNotExist:
return False
diff --git a/archaeological_files/views.py b/archaeological_files/views.py
index 3f7e0bc8b..ad6eff854 100644
--- a/archaeological_files/views.py
+++ b/archaeological_files/views.py
@@ -50,7 +50,8 @@ RE_YEAR_INDEX = re.compile(r"([1-2][0-9]{3})-([0-9]+)") # eg.: 2014-123
def autocomplete_file(request):
if not request.user.has_perm('ishtar_common.view_file', models.File) and \
not request.user.has_perm('ishtar_common.view_own_file', models.File) \
- and not request.user.ishtaruser.has_right('file_search'):
+ and not request.user.ishtaruser.has_right('file_search',
+ session=request.session):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index 7ae6063bc..3af75da23 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -40,7 +40,8 @@ def autocomplete_patriarche(request, non_closed=True):
models.Operation)
and not request.user.has_perm('ishtar_common.view_own_operation',
models.Operation)
- and not request.user.ishtaruser.has_right('operation_search')):
+ and not request.user.ishtaruser.has_right(
+ 'operation_search', session=request.session)):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
@@ -90,9 +91,10 @@ def autocomplete_operation(request, non_closed=True):
# person_types = request.user.ishtaruser.person.person_type
if (not request.user.has_perm('ishtar_common.view_operation',
models.Operation)
- and not request.user.has_perm('ishtar_common.view_own_operation',
- models.Operation)
- and not request.user.ishtaruser.has_right('operation_search')):
+ and not request.user.has_perm(
+ 'ishtar_common.view_own_operation', models.Operation)
+ and not request.user.ishtaruser.has_right(
+ 'operation_search', session=request.session)):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
@@ -116,10 +118,10 @@ def autocomplete_operation(request, non_closed=True):
def get_available_operation_code(request, year=None):
- if not request.user.has_perm('ishtar_common.view_operation',
- models.Operation)\
- and not request.user.has_perm('ishtar_common.view_own_operation',
- models.Operation):
+ if not request.user.has_perm(
+ 'ishtar_common.view_operation', models.Operation)\
+ and not request.user.has_perm(
+ 'ishtar_common.view_own_operation', models.Operation):
return HttpResponse(mimetype='text/plain')
data = json.dumps({'id':
models.Operation.get_available_operation_code(year)})
@@ -365,10 +367,10 @@ administrativact_register_wizard = SearchWizard.as_view([
def generatedoc_administrativeactop(request, pk, template_pk=None):
- if (not request.user.has_perm('ishtar_common.view_operation',
- models.Operation)
- and not request.user.has_perm('ishtar_common.view_own_operation',
- models.Operation)):
+ if (not request.user.has_perm(
+ 'ishtar_common.view_operation', models.Operation)
+ and not request.user.has_perm(
+ 'ishtar_common.view_own_operation', models.Operation)):
return HttpResponse(mimetype='text/plain')
try:
act_file = models.AdministrativeAct.objects.get(pk=pk)
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py
index 10a7b9bf4..22eed80e3 100644
--- a/archaeological_warehouse/views.py
+++ b/archaeological_warehouse/views.py
@@ -41,11 +41,12 @@ get_container = get_item(models.Container,
new_warehouse = new_item(models.Warehouse, WarehouseForm)
new_container = new_item(models.Container, ContainerForm)
+
def autocomplete_warehouse(request):
if not request.user.has_perm('ishtar_common.view_warehouse',
models.Warehouse)\
- and not request.user.has_perm('ishtar_common.view_own_warehouse',
- models.Warehouse) :
+ and not request.user.has_perm(
+ 'ishtar_common.view_own_warehouse', models.Warehouse):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
@@ -61,11 +62,12 @@ def autocomplete_warehouse(request):
for warehouse in warehouses])
return HttpResponse(data, mimetype='text/plain')
+
def autocomplete_container(request):
if not request.user.has_perm('ishtar_common.view_warehouse',
- models.Warehouse)\
- and not request.user.has_perm('ishtar_common.view_own_warehouse',
- models.Warehouse):
+ models.Warehouse)\
+ and not request.user.has_perm(
+ 'ishtar_common.view_own_warehouse', models.Warehouse):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
diff --git a/example_project/settings.py b/example_project/settings.py
index 43917523b..6a0bf4079 100644
--- a/example_project/settings.py
+++ b/example_project/settings.py
@@ -106,7 +106,6 @@ TEMPLATE_DIRS = (
)
AUTHENTICATION_BACKENDS = (
- 'django.contrib.auth.backends.ModelBackend',
'ishtar_common.backend.ObjectPermBackend',
)
diff --git a/ishtar_common/backend.py b/ishtar_common/backend.py
index 7ebdab221..0febd61b2 100644
--- a/ishtar_common/backend.py
+++ b/ishtar_common/backend.py
@@ -21,22 +21,18 @@
Permission backend to manage "own" objects
"""
-from django.conf import settings
-from django.contrib.auth.models import User
+from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.loading import cache
import models
-class ObjectPermBackend(object):
+
+class ObjectPermBackend(ModelBackend):
supports_object_permissions = True
supports_anonymous_user = True
- def authenticate(self, username, password):
- # managed by the default backend
- return None
-
- def has_perm(self, user_obj, perm, model=None, obj=None):
+ def has_perm(self, user_obj, perm, model=None, obj=None, session=None):
if not user_obj.is_authenticated():
return False
if not model:
@@ -50,10 +46,10 @@ class ObjectPermBackend(object):
is_ownperm = perm.split('.')[-1].split('_')[1] == 'own'
except IndexError:
is_ownperm = False
- if ishtar_user.has_right('administrator'):
+ if ishtar_user.has_right('administrator', session=session):
return True
- main_right = ishtar_user.person.has_right(perm) \
- or user_obj.has_perm(perm)
+ main_right = ishtar_user.person.has_right(perm, session=session) \
+ or user_obj.has_perm(perm)
if not main_right or not is_ownperm:
return main_right
if obj is None:
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index 20b7f119a..ce303c344 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -58,7 +58,8 @@ def get_base_context(request):
if 'CURRENT_ACTION' in request.session:
dct['CURRENT_ACTION'] = request.session['CURRENT_ACTION']
current_action = dct['CURRENT_ACTION']
- menu = Menu(request.user, current_action=current_action)
+ menu = Menu(request.user, current_action=current_action,
+ session=request.session)
menu.init()
if menu.selected_idx is not None:
dct['current_theme'] = "theme-%d" % (menu.selected_idx + 1)
diff --git a/ishtar_common/menu_base.py b/ishtar_common/menu_base.py
index 2331ecbd7..ab0a43d41 100644
--- a/ishtar_common/menu_base.py
+++ b/ishtar_common/menu_base.py
@@ -17,6 +17,7 @@
# See the file COPYING for details.
+
class SectionItem:
def __init__(self, idx, label, childs=[]):
self.idx = idx
@@ -25,27 +26,29 @@ class SectionItem:
self.available = False
self.items = {}
- def can_be_available(self, user):
+ def can_be_available(self, user, session=None):
for child in self.childs:
- if child.can_be_available(user):
+ if child.can_be_available(user, session=session):
return True
return False
- def is_available(self, user, obj=None):
+ def is_available(self, user, obj=None, session=None):
for child in self.childs:
- if child.is_available(user, obj):
+ if child.is_available(user, obj, session=session):
return True
return False
- def set_items(self, user, items, current_action=None):
+ def set_items(self, user, items, current_action=None, session=None):
selected = None
if user:
- self.available = self.can_be_available(user)
+ self.available = self.can_be_available(user, session=session)
for child in self.childs:
- selected = child.set_items(user, items, current_action) or selected
+ selected = child.set_items(user, items, current_action,
+ session=session) or selected
items[child.idx] = child
return selected
+
class MenuItem:
def __init__(self, idx, label, model=None, access_controls=[]):
self.idx = idx
@@ -54,22 +57,24 @@ class MenuItem:
self.access_controls = access_controls
self.available = False
- def can_be_available(self, user):
+ def can_be_available(self, user, session=None):
if not self.access_controls:
return True
prefix = (self.model._meta.app_label + '.') if self.model else ''
for access_control in self.access_controls:
access_control = prefix + access_control
- if user.has_perm(access_control, self.model) or \
+ if hasattr(user, 'ishtaruser') and \
+ user.ishtaruser.has_perm(access_control, self.model,
+ session=session) or \
access_control in user.get_group_permissions():
return True
# manage by person type
if hasattr(user, 'ishtaruser'):
- if user.ishtaruser.has_right(self.idx):
+ if user.ishtaruser.has_right(self.idx, session=session):
return True
return False
- def is_available(self, user, obj=None):
+ def is_available(self, user, obj=None, session=None):
if not self.access_controls:
return True
prefix = (self.model._meta.app_label + '.') if self.model else ''
@@ -79,13 +84,12 @@ class MenuItem:
return True
# manage by person type
if hasattr(user, 'ishtaruser'):
- if ishtar_user.has_right(self.idx):
+ if user.ishtaruser.has_right(self.idx, session=session):
return True
return False
- def set_items(self, user, items, current_action=None):
+ def set_items(self, user, items, current_action=None, session=None):
if user:
- self.available = self.can_be_available(user)
+ self.available = self.can_be_available(user, session=session)
if self.idx == current_action:
return True
-
diff --git a/ishtar_common/menus.py b/ishtar_common/menus.py
index 6333a4197..e55b288bf 100644
--- a/ishtar_common/menus.py
+++ b/ishtar_common/menus.py
@@ -22,10 +22,7 @@ Menus
"""
from django.conf import settings
-from django.utils.translation import ugettext_lazy as _
-from menu_base import SectionItem, MenuItem
-import models
_extra_menus = []
# collect menu from INSTALLED_APPS
@@ -36,8 +33,8 @@ for app in settings.INSTALLED_APPS:
_extra_menus += menu.MENU_SECTIONS
# sort
-__section_items = [menu for order, menu in sorted(_extra_menus,
- key=lambda x:x[0])]
+__section_items = [mnu for order, mnu in sorted(_extra_menus,
+ key=lambda x:x[0])]
# regroup menus
_section_items, __keys = [], []
for section_item in __section_items:
@@ -51,22 +48,26 @@ for section_item in __section_items:
if child.idx not in childs_idx:
section_childs.append(child)
+
class Menu:
childs = _section_items
- def __init__(self, user, current_action=None):
+
+ def __init__(self, user, current_action=None, session=None):
self.user = user
self.initialized = False
self.items = {}
self.current_action = current_action
self.selected_idx = None
+ self.session = session
def init(self):
if self.initialized:
return
self.items = {}
for idx, main_menu in enumerate(self.childs):
- selected = main_menu.set_items(self.user, self.items,
- self.current_action)
+ selected = main_menu.set_items(
+ self.user, self.items,
+ self.current_action, session=self.session)
if selected:
self.selected_idx = idx
self.initialized = True
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 72b41e0cf..b5e371b25 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -434,6 +434,18 @@ class GeneralType(models.Model):
for item in cls.objects.all():
item.generate_key()
+ @classmethod
+ def get_cache(cls, slug):
+ cache_key, value = get_cache(cls, slug)
+ if value:
+ return value
+ try:
+ obj = cls.objects.get(txt_idx=slug)
+ cache.set(cache_key, obj, settings.CACHE_TIMEOUT)
+ return obj
+ except cls.DoesNotExist:
+ return None
+
class ItemKey(models.Model):
key = models.CharField(_(u"Key"), max_length=100)
@@ -1938,19 +1950,29 @@ class Person(Address, Merge, OwnPerms, ValueGetter):
def is_natural(self):
return not self.attached_to
- def has_right(self, right_name):
+ def has_right(self, right_name, session=None):
if '.' in right_name:
right_name = right_name.split('.')[-1]
+ res, cache_key = "", ""
+ if session:
+ cache_key = 'session-{}-{}'.format(session.session_key, right_name)
+ res = cache.get(cache_key)
+ if res in (True, False):
+ return res
if type(right_name) in (list, tuple):
- return bool(self.person_types.filter(
+ res = bool(self.person_types.filter(
txt_idx__in=right_name).count()) or \
bool(self.person_types.filter(
groups__permissions__codename__in=right_name).count())
# or self.person_types.filter(wizard__url_name__in=right_name).count())
- return bool(self.person_types.filter(txt_idx=right_name).count()) or \
- bool(self.person_types.filter(
- groups__permissions__codename=right_name).count())
+ else:
+ res = bool(self.person_types.filter(txt_idx=right_name).count()) or \
+ bool(self.person_types.filter(
+ groups__permissions__codename=right_name).count())
# or self.person_types.filter(wizard__url_name=right_name).count())
+ if session:
+ cache.set(cache_key, res, settings.CACHE_SMALLTIMEOUT)
+ return res
def full_label(self):
values = []
@@ -2010,12 +2032,24 @@ class IshtarUser(User):
return IshtarUser.objects.create(user_ptr=user, username=default,
person=person)
- def has_right(self, right_name):
- return self.person.has_right(right_name)
+ def has_right(self, right_name, session=None):
+ return self.person.has_right(right_name, session=session)
def full_label(self):
return self.person.full_label()
+ def has_perm(self, perm, model=None, session=None):
+ if not session:
+ return super(IshtarUser, self).has_perm(perm, model)
+ cache_key = 'usersession-{}-{}'.format(session.session_key, perm,
+ model or 'no')
+ res = cache.get(cache_key)
+ if res in (True, False):
+ return res
+ res = super(IshtarUser, self).has_perm(perm, model)
+ cache.set(cache_key, res, settings.CACHE_SMALLTIMEOUT)
+ return res
+
class AuthorType(GeneralType):
class Meta:
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index ac29236ff..79e816bcb 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -167,21 +167,27 @@ def check_permission(request, action_slug, obj_id=None):
# TODO
return True
if obj_id:
- return menu.items[action_slug].is_available(request.user, obj_id)
- return menu.items[action_slug].can_be_available(request.user)
+ return menu.items[action_slug].is_available(request.user, obj_id,
+ session=request.session)
+ return menu.items[action_slug].can_be_available(request.user,
+ session=request.session)
-def autocomplete_person_permissive(request, person_types=None, attached_to=None,
- is_ishtar_user=None):
- return autocomplete_person(request, person_types=person_types, attached_to=attached_to,
- is_ishtar_user=is_ishtar_user, permissive=True)
+def autocomplete_person_permissive(request, person_types=None,
+ attached_to=None, is_ishtar_user=None):
+ return autocomplete_person(
+ request, person_types=person_types, attached_to=attached_to,
+ is_ishtar_user=is_ishtar_user, permissive=True)
def autocomplete_person(request, person_types=None, attached_to=None,
is_ishtar_user=None, permissive=False):
- if not request.user.has_perm('ishtar_common.view_person', models.Person) and \
- not request.user.has_perm('ishtar_common.view_own_person', models.Person) \
- and not request.user.ishtaruser.has_right('person_search'):
+ if not request.user.has_perm('ishtar_common.view_person',
+ models.Person) and \
+ not request.user.has_perm('ishtar_common.view_own_person',
+ models.Person) \
+ and not request.user.ishtaruser.has_right('person_search',
+ session=request.session):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
@@ -325,7 +331,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
continue
if request.user.has_perm(model._meta.app_label + '.' + perm) \
or (request.user.is_authenticated()
- and request.user.ishtaruser.has_right(perm)):
+ and request.user.ishtaruser.has_right(
+ perm, session=request.session)):
allowed = True
if "_own_" not in perm:
own = False
@@ -760,7 +767,8 @@ def autocomplete_organization(request, orga_type=None):
models.Organization) and
not request.user.has_perm('ishtar_common.view_own_organization',
models.Organization)
- and not request.user.ishtaruser.has_right('person_search')):
+ and not request.user.ishtaruser.has_right(
+ 'person_search', session=request.session)):
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index 8fe1b5da2..45b46eb63 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -74,8 +74,8 @@ class Wizard(NamedUrlWizardView):
# TODO: to be check
if not hasattr(self.request.user, 'ishtaruser'):
return False
- return self.request.user.ishtaruser.has_right(('administrator',
- step))
+ return self.request.user.ishtaruser.has_right(
+ ('administrator', step), session=self.request.session)
return check_right
def __init__(self, *args, **kwargs):