improve access permission querying

This commit is contained in:
Laura Klünder 2017-12-20 21:17:35 +01:00
parent 544b3dae2e
commit 385aebe445
2 changed files with 44 additions and 34 deletions

View file

@ -8,7 +8,6 @@ from itertools import chain
import pytz import pytz
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.models import Q
from django.forms import ChoiceField, Form, ModelForm from django.forms import ChoiceField, Form, ModelForm
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -16,7 +15,8 @@ from django.utils.translation import ungettext_lazy
from c3nav.control.models import UserPermissions from c3nav.control.models import UserPermissions
from c3nav.mapdata.forms import I18nModelFormMixin from c3nav.mapdata.forms import I18nModelFormMixin
from c3nav.mapdata.models.access import AccessPermissionToken, AccessPermissionTokenItem, AccessRestriction from c3nav.mapdata.models.access import (AccessPermission, AccessPermissionToken, AccessPermissionTokenItem,
AccessRestriction, AccessRestrictionGroup)
from c3nav.site.models import Announcement from c3nav.site.models import Announcement
@ -37,18 +37,11 @@ class AccessPermissionForm(Form):
self.expire_date = expire_date self.expire_date = expire_date
# determine which access permissions the author can grant # determine which access permissions the author can grant
if not author_permissions.grant_all_access: self.author_access_permissions = AccessPermission.get_for_request_with_expire_date(request, can_grant=True)
self.author_access_permissions = {
pk: expire_date for pk, expire_date in self.author.accesspermissions.filter( access_restrictions = AccessRestriction.objects.filter(
Q(can_grant=True) & (Q(expire_date__isnull=True) | Q(expire_date__lt=timezone.now())) pk__in=self.author_access_permissions.keys()
).values_list('access_restriction_id', 'expire_date') )
}
access_restrictions = AccessRestriction.objects.filter(
pk__in=self.author_access_permissions.keys()
)
else:
self.author_access_permissions = {}
access_restrictions = AccessRestriction.objects.all()
self.access_restrictions = { self.access_restrictions = {
access_restriction.pk: access_restriction access_restriction.pk: access_restriction

View file

@ -151,36 +151,53 @@ class AccessPermission(models.Model):
def user_access_permission_key(user_id): def user_access_permission_key(user_id):
return 'mapdata:user_access_permission:%d' % user_id return 'mapdata:user_access_permission:%d' % user_id
@classmethod
def get_for_request_with_expire_date(cls, request, can_grant=None):
if not request.user.is_authenticated:
return {}
if request.user_permissions.grant_all_access:
return {pk: None for pk in cls.get_all_access_restrictions()}
result = tuple(request.user.accesspermissions.filter(
Q(expire_date__isnull=True) | Q(expire_date__gt=timezone.now())
).filter(
Q(can_grant=True) if can_grant is not None else Q()
).values_list('access_restriction_id', 'expire_date'))
# collect permissions (can be multiple for one restriction)
permissions = {}
for access_restriction_id, expire_date in result:
permissions.setdefault(access_restriction_id, set()).add(expire_date)
# get latest expire date for each permission
permissions = {
access_restriction_id: None if None in expire_dates else max(expire_dates)
for access_restriction_id, expire_dates in permissions.items()
}
return permissions
@staticmethod
def get_all_access_restrictions():
cache_key = 'all_access_restrictions:%s' % MapUpdate.current_cache_key()
access_restriction_ids = cache.get(cache_key, None)
if access_restriction_ids is None:
access_restriction_ids = set(AccessRestriction.objects.values_list('pk', flat=True))
cache.set(cache_key, access_restriction_ids, 300)
return access_restriction_ids
@classmethod @classmethod
def get_for_request(cls, request): def get_for_request(cls, request):
if not request.user.is_authenticated: if not request.user.is_authenticated:
return set() return set()
if request.user_permissions.grant_all_access: if request.user_permissions.grant_all_access:
cache_key = 'all_access_restrictions:%s' % MapUpdate.current_cache_key() return cls.get_all_access_restrictions()
access_restriction_ids = cache.get(cache_key, None)
if access_restriction_ids is None:
access_restriction_ids = set(AccessRestriction.objects.values_list('pk', flat=True))
cache.set(cache_key, access_restriction_ids, 300)
return access_restriction_ids
cache_key = cls.user_access_permission_key(request.user.pk) cache_key = cls.user_access_permission_key(request.user.pk)
access_restriction_ids = cache.get(cache_key, None) access_restriction_ids = cache.get(cache_key, None)
if access_restriction_ids is None: if access_restriction_ids is None:
result = tuple(request.user.accesspermissions.filter( permissions = cls.get_for_request_with_expire_date(request)
Q(expire_date__isnull=True) | Q(expire_date__gt=timezone.now())
).values_list('access_restriction_id', 'expire_date'))
# collect permissions (can be multiple for one restriction)
permissions = {}
for access_restriction_id, expire_date in result:
permissions.setdefault(access_restriction_id, set()).add(expire_date)
# get latest expire date for each permission
permissions = {
access_restriction_id: None if None in expire_dates else max(expire_dates)
for access_restriction_id, expire_dates in permissions.items()
}
access_restriction_ids = set(permissions.keys()) access_restriction_ids = set(permissions.keys())