Commit 4df53ca9 authored by chirac's avatar chirac Committed by Gabriel Detraz
Browse files

Add can_list acl, move views autocomplete mixins to re2o/views.py

parent b418719e
......@@ -37,7 +37,7 @@ from .models import (
Banque
)
from re2o.mixins import AutocompleteViewMixin
from re2o.views import AutocompleteViewMixin
from re2o.acl import (
can_view_all,
......
......@@ -369,6 +369,15 @@ def can_view_all(*targets):
return acl_base_decorator("can_view_all", *targets, on_instance=False)
def can_list(*targets):
"""Decorator to check if an user can list a class of model.
It runs `acl_base_decorator` with the flag `on_instance=False` and the
method 'can_list'. See `acl_base_decorator` documentation for further
details.
"""
return acl_base_decorator("can_list", *targets, on_instance=False)
def can_view_app(*apps_name):
"""Decorator to check if an user can view the applications."""
for app_name in apps_name:
......
......@@ -29,6 +29,7 @@ from django.utils.translation import ugettext as _
from dal import autocomplete
class RevMixin(object):
"""A mixin to subclass the save and delete function of a model
to enforce the versioning of the object before those actions
......@@ -80,6 +81,8 @@ class AclMixin(object):
:can_view: Applied on an instance, return if the user can view the
instance
:can_view_all: Applied on a class, return if the user can view all
instances
:can_list: Applied on a class, return if the user can list all
instances"""
@classmethod
......@@ -209,6 +212,28 @@ class AclMixin(object):
(permission,),
)
@classmethod
def can_list(cls, user_request, *_args, **_kwargs):
"""Check if a user can list all instances of an object
Parameters:
user_request: User calling for this action
Returns:
Boolean: True if user_request has the right access to do it, else
false with reason for reject authorization
"""
permission = cls.get_modulename() + ".view_" + cls.get_classname()
can = user_request.has_perm(permission)
return (
can,
_("You don't have the right to list every %s object.") % cls.get_classname()
if not can
else None,
(permission,),
cls.objects.all() if can else None,
)
def can_view(self, user_request, *_args, **_kwargs):
"""Check if a user can view an instance of an object
......@@ -272,13 +297,3 @@ class AutocompleteMultipleModelMixin(autocomplete.ModelSelect2Multiple):
attrs["data-minimum-results-for-search"] = attrs.get("data-minimum-results-for-search", 10)
return attrs
class AutocompleteViewMixin(autocomplete.Select2QuerySetView):
obj_type = None # This MUST be overridden by child class
query_filter = "name__icontains" # Override this if necessary
def get_queryset(self):
query_set = self.obj_type.objects.all()
if self.q:
query_set = query_set.filter(**{ self.query_filter: self.q})
return query_set
......@@ -141,6 +141,8 @@ def get_callback(tag_name, obj=None):
return acl_fct(obj.can_view_all, False)
if tag_name == "cannot_view_all":
return acl_fct(obj.can_view_all, True)
if tag_name == "can_list":
return acl_fct(obj.can_list, False)
if tag_name == "can_view_app":
return acl_fct(
lambda x: (
......@@ -296,6 +298,7 @@ def acl_change_filter(parser, token):
@register.tag("cannot_delete_all")
@register.tag("can_view_all")
@register.tag("cannot_view_all")
@register.tag("can_list")
def acl_model_filter(parser, token):
"""Generic definition of an acl templatetag for acl based on model"""
......
......@@ -33,6 +33,10 @@ from django.template.context_processors import csrf
from django.conf import settings
from django.utils.translation import ugettext as _
from django.views.decorators.cache import cache_page
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.decorators import method_decorator
from dal import autocomplete
from preferences.models import (
Service,
......@@ -43,6 +47,7 @@ from preferences.models import (
Mandate,
)
from .acl import can_list
from .contributors import CONTRIBUTORS
from importlib import import_module
from re2o.settings_local import OPTIONNAL_APPS_RE2O
......@@ -169,3 +174,21 @@ def handler500(request):
def handler404(request):
"""The handler view for a 404 error"""
return render(request, "errors/404.html", status=404)
class AutocompleteViewMixin(LoginRequiredMixin, autocomplete.Select2QuerySetView):
obj_type = None # This MUST be overridden by child class
query_set = None
query_filter = "name__icontains" # Override this if necessary
def get_queryset(self):
can, reason, _permission, query_set = self.obj_type.can_list(self.request.user)
self.query_set = query_set
if hasattr(self, "filter_results"):
self.filter_results()
else:
if self.q:
self.query_set = self.query_set.filter(**{ self.query_filter: self.q})
return self.query_set
......@@ -44,7 +44,7 @@ from .models import (
SwitchBay,
)
from re2o.mixins import AutocompleteViewMixin
from re2o.views import AutocompleteViewMixin
from re2o.acl import (
can_view_all,
......
......@@ -45,7 +45,7 @@ from .models import (
EMailAddress,
)
from re2o.mixins import AutocompleteViewMixin
from re2o.views import AutocompleteViewMixin
from re2o.acl import (
can_view_all,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment