From 048bcfad26842b252093d1c37ad4bc9a5fb338b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Sat, 9 Dec 2017 01:15:11 +0000 Subject: [PATCH] Create can_delete and can_view decorators and use them where it's possible --- cotisations/views.py | 15 +++-------- machines/models.py | 10 +++++--- machines/views.py | 57 +++++++++++------------------------------- re2o/utils.py | 59 +++++++++++++++++++++++++++++++++++++++++--- users/views.py | 13 ++++------ 5 files changed, 86 insertions(+), 68 deletions(-) diff --git a/cotisations/views.py b/cotisations/views.py index 8b1661b5..e7405d0f 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -43,7 +43,7 @@ from users.models import User from re2o.settings import LOGO_PATH from re2o import settings from re2o.views import form -from re2o.utils import SortTable, can_create, can_edit +from re2o.utils import SortTable, can_create, can_edit, can_delete, can_view from preferences.models import OptionalUser, AssoOption, GeneralOption from .models import Facture, Article, Vente, Paiement, Banque from .forms import ( @@ -284,19 +284,10 @@ def edit_facture(request, facture, factureid): @login_required -@permission_required('cableur') -def del_facture(request, factureid): +@can_delete(Facture) +def del_facture(request, facture, factureid): """Suppression d'une facture. Supprime en cascade les ventes et cotisations filles""" - try: - facture = Facture.objects.get(pk=factureid) - except Facture.DoesNotExist: - messages.error(request, u"Facture inexistante") - return redirect(reverse('cotisations:index')) - if facture.control or not facture.valid: - messages.error(request, "Vous ne pouvez pas editer une facture\ - controlée ou invalidée par le trésorier") - return redirect(reverse('cotisations:index')) if request.method == "POST": with transaction.atomic(), reversion.create_revision(): facture.delete() diff --git a/machines/models.py b/machines/models.py index 08cc3bcf..cafc1ea4 100644 --- a/machines/models.py +++ b/machines/models.py @@ -837,7 +837,7 @@ class Interface(models.Model): d'un autre user que vous sans droit" return True, None - def can_delete(self, user_resquest, *args, **kwargs): + def can_delete(self, user_request, *args, **kwargs): if not user_request.has_perms(('cableur',)) and self.machine.user != user_request: return False, u"Vous ne pouvez pas éditer une machine d'un autre\ user que vous sans droit" @@ -1177,8 +1177,12 @@ class OuverturePortList(models.Model): return True, None def can_delete(self, user_request, *args, **kwargs): - return user_request.has_perms(('bureau',)), u"Vous n'avez pas le droit\ - de supprimer une ouverture de port" + if not user_request.has_perms(('bureau',)): + return False, u"Vous n'avez pas le droit de supprimer une ouverture\ + de port" + if self.interface_set.all(): + return False, u"Cette liste de ports est utilisée" + return True, None def can_view(self, user_request, *args, **kwargs): return user_request.has_perms(('cableur',)), u"Vous n'avez pas le droit\ diff --git a/machines/views.py b/machines/views.py index 32bfc712..ddc56400 100644 --- a/machines/views.py +++ b/machines/views.py @@ -125,7 +125,9 @@ from re2o.utils import ( filter_active_interfaces, SortTable, can_create, - can_edit + can_edit, + can_delete, + can_view ) from re2o.views import form @@ -213,12 +215,12 @@ def generate_ipv4_mbf_param( form, is_type_tt ): @login_required @can_create(Machine) -def new_machine(request, userid): +@can_edit(User) +def new_machine(request, user, userid): """ Fonction de creation d'une machine. Cree l'objet machine, le sous objet interface et l'objet domain à partir de model forms. Trop complexe, devrait être simplifié""" - user = User.objects.get(pk=userid) machine = NewMachineForm(request.POST or None) interface = AddInterfaceForm( request.POST or None, @@ -328,10 +330,10 @@ def del_machine(request, machineid): @login_required @can_create(Interface) -def new_interface(request, machineid): +@can_edit(Machine) +def new_interface(request, machine, machineid): """ Ajoute une interface et son domain associé à une machine existante""" - machine = Machine.objects.get(pk=machineid) interface_form = AddInterfaceForm(request.POST or None, infra=request.user.has_perms(('infra',))) domain_form = DomainForm(request.POST or None) if interface_form.is_valid(): @@ -358,20 +360,9 @@ def new_interface(request, machineid): return form({'interfaceform': interface_form, 'domainform': domain_form, 'i_mbf_param': i_mbf_param}, 'machines/machine.html', request) @login_required -def del_interface(request, interfaceid): +@can_delete(Interface) +def del_interface(request, interface, interfaceid): """ Supprime une interface. Domain objet en mode cascade""" - try: - interface = Interface.objects.get(pk=interfaceid) - except Interface.DoesNotExist: - messages.error(request, u"Interface inexistante" ) - return redirect(reverse('machines:index')) - if not request.user.has_perms(('cableur',)): - if interface.machine.user != request.user: - messages.error(request, "Vous ne pouvez pas éditer une machine d'un autre user que vous sans droit") - return redirect(reverse( - 'users:profil', - kwargs={'userid':str(request.user.id)} - )) if request.method == "POST": machine = interface.machine with transaction.atomic(), reversion.create_revision(): @@ -751,9 +742,9 @@ def del_srv(request): @login_required @can_create(Domain) -def add_alias(request, interfaceid): +@can_edit(Interface) +def add_alias(request, interface, interfaceid): - interface = Interface.objects.get(pk=interfaceid) alias = AliasForm(request.POST or None, infra=request.user.has_perms(('infra',))) if alias.is_valid(): alias = alias.save(commit=False) @@ -787,18 +778,8 @@ def edit_alias(request, domain_instance, domainid): return form({'aliasform': alias}, 'machines/machine.html', request) @login_required -def del_alias(request, interfaceid): - try: - interface = Interface.objects.get(pk=interfaceid) - except Interface.DoesNotExist: - messages.error(request, u"Interface inexistante" ) - return redirect(reverse('machines:index')) - if not request.user.has_perms(('cableur',)) and interface.machine.user != request.user: - messages.error(request, "Vous ne pouvez pas ajouter un alias à une machine d'un autre user que vous sans droit") - return redirect(reverse( - 'users:profil', - kwargs={'userid':str(request.user.id)} - )) +@can_edit(Interface) +def del_alias(request, interface, interfaceid): alias = DelAliasForm(request.POST or None, interface=interface) if alias.is_valid(): alias_dels = alias.cleaned_data['alias'] @@ -1191,16 +1172,8 @@ def edit_portlist(request, ouvertureportlist_instance, ouvertureportlistid): return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request) @login_required -@permission_required('bureau') -def del_portlist(request, ouvertureportlistid): - try: - port_list_instance = OuverturePortList.objects.get(pk=ouvertureportlistid) - except OuverturePortList.DoesNotExist: - messages.error(request, "Liste de ports inexistante") - return redirect(reverse('machines:index-portlist')) - if port_list_instance.interface_set.all(): - messages.error(request, "Cette liste de ports est utilisée") - return redirect(reverse('machines:index-portlist')) +@can_delete(OuverturePortList) +def del_portlist(request, port_list_instance, ouvertureportlistid): port_list_instance.delete() messages.success(request, "La liste de ports a été supprimée") return redirect(reverse('machines:index-portlist')) diff --git a/re2o/utils.py b/re2o/utils.py index 1f8143cb..f77c03a5 100644 --- a/re2o/utils.py +++ b/re2o/utils.py @@ -72,9 +72,9 @@ def can_create(model): def can_edit(model): """Decorator to check if an user can edit a model. It tries to get an instance of the model, using - `model.get_instance(*args, **kwargs)` and assumes that the model has a method - `can_create(user)` which returns `true` if the user can create this kind - of models. + `model.get_instance(*args, **kwargs)` and assumes that the model has a + method `can_edit(user)` which returns `true` if the user can edit this + kind of models. """ def decorator(view): def wrapper(request, *args, **kwargs): @@ -96,6 +96,59 @@ def can_edit(model): return decorator +def can_delete(model): + """Decorator to check if an user can delete a model. + It tries to get an instance of the model, using + `model.get_instance(*args, **kwargs)` and assumes that the model has a + method `can_delete(user)` which returns `true` if the user can delete this + kind of models. + """ + def decorator(view): + def wrapper(request, *args, **kwargs): + try: + instance = model.get_instance(*args, **kwargs) + except model.DoesNotExist: + messages.error(request, u"Entrée inexistante") + return redirect(reverse('users:profil', + kwargs={'userid':str(request.user.id)} + )) + can, msg = instance.can_delete(request.user) + if not can: + messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu") + return redirect(reverse('users:profil', + kwargs={'userid':str(request.user.id)} + )) + return view(request, instance, *args, **kwargs) + return wrapper + return decorator + + +def can_view(model): + """Decorator to check if an user can view a model. + It tries to get an instance of the model, using + `model.get_instance(*args, **kwargs)` and assumes that the model has a + method `can_view(user)` which returns `true` if the user can view this + kind of models. + """ + def decorator(view): + def wrapper(request, *args, **kwargs): + try: + instance = model.get_instance(*args, **kwargs) + except model.DoesNotExist: + messages.error(request, u"Entrée inexistante") + return redirect(reverse('users:profil', + kwargs={'userid':str(request.user.id)} + )) + can, msg = instance.can_view(request.user) + if not can: + messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu") + return redirect(reverse('users:profil', + kwargs={'userid':str(request.user.id)} + )) + return view(request, instance, *args, **kwargs) + return wrapper + return decorator + def all_adherent(search_time=DT_NOW): """ Fonction renvoyant tous les users adherents. Optimisee pour n'est diff --git a/users/views.py b/users/views.py index 85510f79..a506e160 100644 --- a/users/views.py +++ b/users/views.py @@ -92,7 +92,9 @@ from machines.models import Machine from preferences.models import OptionalUser, GeneralOption from re2o.views import form -from re2o.utils import all_has_access, SortTable, can_create, can_edit +from re2o.utils import ( + all_has_access, SortTable, can_create, can_edit, can_delete, can_view +) def password_change_action(u_form, user, request, req=False): """ Fonction qui effectue le changeemnt de mdp bdd""" @@ -303,14 +305,9 @@ def edit_serviceuser(request, user, userid): @login_required -@permission_required('infra') -def del_serviceuser(request, userid): +@can_delete(ServiceUser) +def del_serviceuser(request, user, userid): """Suppression d'un ou plusieurs serviceusers""" - try: - user = ServiceUser.objects.get(pk=userid) - except ServiceUser.DoesNotExist: - messages.error(request, u"Utilisateur inexistant") - return redirect(reverse('users:index')) if request.method == "POST": with transaction.atomic(), reversion.create_revision(): user.delete()