8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-30 08:32:26 +00:00

helpful acl messages structure

This commit is contained in:
Hugo Levy-Falk 2019-09-06 01:08:53 +02:00
parent 0f063bd187
commit eaf9609024
2 changed files with 42 additions and 9 deletions

View file

@ -36,6 +36,22 @@ from django.shortcuts import redirect
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from re2o.utils import get_group_having_permission
def group_list(permissions):
"""Create a string listing every groups having one of the given
`permissions`."""
if permissions:
return ", ".join([
g.name for g in get_group_having_permission(*permissions)
]) or "No group have the %s permission(s) !" % " or ".join([
",".join(permissions[:-1]),
permissions[-1]] if len(permissions) > 2 else permissions
)
else:
return ""
def acl_base_decorator(method_name, *targets, on_instance=True): def acl_base_decorator(method_name, *targets, on_instance=True):
"""Base decorator for acl. It checks if the `request.user` has the """Base decorator for acl. It checks if the `request.user` has the
@ -53,9 +69,10 @@ def acl_base_decorator(method_name, *targets, on_instance=True):
then no error will be triggered, the decorator will act as if then no error will be triggered, the decorator will act as if
permission was granted. This is to allow you to run ACL tests on permission was granted. This is to allow you to run ACL tests on
fields only. If the method exists, it has to return a 2-tuple fields only. If the method exists, it has to return a 2-tuple
`(can, reason)` with `can` being a boolean stating whether the `(can, reason, permissions)` with `can` being a boolean stating
access is granted and `reason` a message to be displayed if `can` whether the access is granted, `reason` a message to be
equals `False` (can be `None`) displayed if `can` equals `False` (can be `None`) and `permissions`
a list of permissions needed for access (can be `None`).
*targets: The targets. Targets are specified like a sequence of models *targets: The targets. Targets are specified like a sequence of models
and fields names. As an example and fields names. As an example
``` ```
@ -139,7 +156,7 @@ ModelC)
target = target.get_instance(*args, **kwargs) target = target.get_instance(*args, **kwargs)
instances.append(target) instances.append(target)
except target.DoesNotExist: except target.DoesNotExist:
yield False, _("Nonexistent entry.") yield False, _("Nonexistent entry."), []
return return
if hasattr(target, method_name): if hasattr(target, method_name):
can_fct = getattr(target, method_name) can_fct = getattr(target, method_name)
@ -148,11 +165,16 @@ ModelC)
can_change_fct = getattr(target, 'can_change_' + field) can_change_fct = getattr(target, 'can_change_' + field)
yield can_change_fct(request.user, *args, **kwargs) yield can_change_fct(request.user, *args, **kwargs)
error_messages = [ error_messages = []
x[1] for x in chain.from_iterable( for target, fields in group_targets():
process_target(x[0], x[1]) for x in group_targets() for can, msg, permissions in process_target(target, fields):
) if not x[0] if not can:
] error_messages.append(
msg + _(
" You need to be a member of one of those"
" groups : %s"
) % group_list(permissions)
)
if error_messages: if error_messages:
for msg in error_messages: for msg in error_messages:
messages.error( messages.error(

View file

@ -38,12 +38,23 @@ from __future__ import unicode_literals
from django.utils import timezone from django.utils import timezone
from django.db.models import Q from django.db.models import Q
from django.contrib.auth.models import Permission
from cotisations.models import Cotisation, Facture, Vente from cotisations.models import Cotisation, Facture, Vente
from machines.models import Interface, Machine from machines.models import Interface, Machine
from users.models import Adherent, User, Ban, Whitelist from users.models import Adherent, User, Ban, Whitelist
from preferences.models import AssoOption from preferences.models import AssoOption
def get_group_having_permission(*permission_name):
"""Returns every group having the permission `permission_name`
"""
groups = set()
for name in permission_name:
app_label, codename = name.split('.')
permission = Permission.objects.get(content_type__app_label=app_label, codename=codename)
groups = groups.union(permission.group_set.all())
return groups
def all_adherent(search_time=None, including_asso=True): def all_adherent(search_time=None, including_asso=True):
""" Fonction renvoyant tous les users adherents. Optimisee pour n'est """ Fonction renvoyant tous les users adherents. Optimisee pour n'est
qu'une seule requete sql qu'une seule requete sql