From 8ab23e292541894f67ee37fcbc3332c4ce2e2a63 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sun, 31 Dec 2017 00:23:59 +0100 Subject: [PATCH] Gestion des acl avec les permissions django pour cotisation --- cotisations/models.py | 99 ++++++++++++++------- re2o/field_permissions.py | 3 - users/migrations/0061_auto_20171230_2033.py | 31 +++++++ users/models.py | 80 +---------------- 4 files changed, 101 insertions(+), 112 deletions(-) create mode 100644 users/migrations/0061_auto_20171230_2033.py diff --git a/cotisations/models.py b/cotisations/models.py index 36550c2e..d154654d 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -80,6 +80,12 @@ class Facture(FieldPermissionModelMixin, models.Model): class Meta: abstract = False + permissions = ( + ("change_facture_control", "Peut changer l'etat de controle"), + ("change_facture_pdf", "Peut éditer une facture pdf"), + ("view_facture", "Peut voir un objet facture"), + ("change_all_facture", "Superdroit, peut modifier toutes les factures"), + ) def prix(self): """Renvoie le prix brut sans les quantités. Méthode @@ -112,13 +118,13 @@ class Facture(FieldPermissionModelMixin, models.Model): return Facture.objects.get(pk=factureid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_facture'), u"Vous n'avez pas le\ droit de créer des factures" def can_edit(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.change_facture'): return False, u"Vous n'avez pas le droit d'éditer les factures" - elif not user_request.has_perms(('tresorier',)) and\ + elif not user_request.has_perm('cotisation.change_all_facture') and\ (self.control or not self.valid): return False, u"Vous n'avez pas le droit d'éditer une facture\ controlée ou invalidée par un trésorier" @@ -126,7 +132,7 @@ class Facture(FieldPermissionModelMixin, models.Model): return True, None def can_delete(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.delete_facture'): return False, u"Vous n'avez pas le droit de supprimer une facture" if self.control or not self.valid: return False, u"Vous ne pouvez pas supprimer une facture\ @@ -135,12 +141,12 @@ class Facture(FieldPermissionModelMixin, models.Model): return True, None def can_view_all(user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.view_facture'): return False, u"Vous n'avez pas le droit de voir les factures" return True, None def can_view(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)) and\ + if not user_request.has_perm('cotisation.view_facture') and\ self.user != user_request: return False, u"Vous ne pouvez pas afficher l'historique d'une\ facture d'un autre user que vous sans droit cableur" @@ -207,6 +213,12 @@ class Vente(models.Model): max_length=255 ) + class Meta: + permissions = ( + ("view_vente", "Peut voir un objet vente"), + ("change_all_vente", "Superdroit, peut modifier toutes les ventes"), + ) + def prix_total(self): """Renvoie le prix_total de self (nombre*prix)""" return self.prix*self.number @@ -263,14 +275,14 @@ class Vente(models.Model): return Vente.objects.get(pk=venteid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_vente'), u"Vous n'avez pas le\ droit de créer des ventes" return True, None def can_edit(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.change_vente'): return False, u"Vous n'avez pas le droit d'éditer les ventes" - elif not user_request.has_perms(('tresorier',)) and\ + elif not user_request.has_perm('cotisation.change_all_vente') and\ (self.facture.control or not self.facture.valid): return False, u"Vous n'avez pas le droit d'éditer une vente\ controlée ou invalidée par un trésorier" @@ -278,7 +290,7 @@ class Vente(models.Model): return True, None def can_delete(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.delete_vente'): return False, u"Vous n'avez pas le droit de supprimer une vente" if self.facture.control or not self.facture.valid: return False, u"Vous ne pouvez pas supprimer une vente\ @@ -287,12 +299,12 @@ class Vente(models.Model): return True, None def can_view_all(user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.view_vente'): return False, u"Vous n'avez pas le droit de voir les ventes" return True, None def can_view(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)) and\ + if not user_request.has_perm('cotisation.view_vente') and\ self.facture.user != user_request: return False, u"Vous ne pouvez pas afficher l'historique d'une\ facture d'un autre user que vous sans droit cableur" @@ -367,6 +379,11 @@ class Article(models.Model): unique_together = ('name', 'type_user') + class Meta: + permissions = ( + ("view_article", "Peut voir un objet article"), + ) + def clean(self): if self.name.lower() == "solde": raise ValidationError("Solde est un nom d'article invalide") @@ -379,23 +396,23 @@ class Article(models.Model): return Article.objects.get(pk=articleid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_article'), u"Vous n'avez pas le\ droit d'ajouter des articles" def can_edit(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.change_article'), u"Vous n'avez pas le\ droit d'éditer des articles" def can_delete(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.delete_article'), u"Vous n'avez pas le\ droit de supprimer des articles" def can_view_all(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_article'), u"Vous n'avez pas le\ droit de voir des articles" def can_view(self, user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_article'), u"Vous n'avez pas le\ droit de voir des articles" def __str__(self): @@ -408,27 +425,32 @@ class Banque(models.Model): name = models.CharField(max_length=255) + class Meta: + permissions = ( + ("view_banque", "Peut voir un objet banque"), + ) + def get_instance(banqueid, *args, **kwargs): return Banque.objects.get(pk=banqueid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_banque'), u"Vous n'avez pas le\ droit d'ajouter des banques" def can_edit(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.change_banque'), u"Vous n'avez pas le\ droit d'éditer des banques" def can_delete(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.delete_banque'), u"Vous n'avez pas le\ droit de supprimer des banques" def can_view_all(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_banque'), u"Vous n'avez pas le\ droit de voir des banques" def can_view(self, user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_banque'), u"Vous n'avez pas le\ droit de voir des banques" def __str__(self): @@ -446,27 +468,32 @@ class Paiement(models.Model): moyen = models.CharField(max_length=255) type_paiement = models.IntegerField(choices=PAYMENT_TYPES, default=0) + class Meta: + permissions = ( + ("view_paiement", "Peut voir un objet paiement"), + ) + def get_instance(paiementid, *args, **kwargs): return Paiement.objects.get(pk=paiementid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_paiement'), u"Vous n'avez pas le\ droit d'ajouter des paiements" def can_edit(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.change_paiement'), u"Vous n'avez pas le\ droit d'éditer des paiements" def can_delete(self, user_request, *args, **kwargs): - return user_request.has_perms(('tresorier',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.delete_paiement'), u"Vous n'avez pas le\ droit de supprimer des paiements" def can_view_all(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_paiement'), u"Vous n'avez pas le\ droit de voir des paiements" def can_view(self, user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.view_paiement'), u"Vous n'avez pas le\ droit de voir des paiements" def __str__(self): @@ -501,18 +528,24 @@ class Cotisation(models.Model): date_start = models.DateTimeField() date_end = models.DateTimeField() + class Meta: + permissions = ( + ("view_cotisation", "Peut voir un objet cotisation"), + ("change_all_cotisation", "Superdroit, peut modifier toutes les cotisations"), + ) + def get_instance(cotisationid, *args, **kwargs): return Cotisations.objects.get(pk=cotisationid) def can_create(user_request, *args, **kwargs): - return user_request.has_perms(('cableur',)), u"Vous n'avez pas le\ + return user_request.has_perm('cotisation.add_cotisation'), u"Vous n'avez pas le\ droit de créer des cotisations" return True, None def can_edit(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.change_cotisation'): return False, u"Vous n'avez pas le droit d'éditer les cotisations" - elif not user_request.has_perms(('tresorier',)) and\ + elif not user_request.has_perm('cotisation.change_all_cotisation') and\ (self.vente.facture.control or not self.vente.facture.valid): return False, u"Vous n'avez pas le droit d'éditer une cotisation\ controlée ou invalidée par un trésorier" @@ -520,7 +553,7 @@ class Cotisation(models.Model): return True, None def can_delete(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.delete_cotisation'): return False, u"Vous n'avez pas le droit de supprimer une cotisations" if self.vente.facture.control or not self.vente.facture.valid: return False, u"Vous ne pouvez pas supprimer une cotisations\ @@ -529,12 +562,12 @@ class Cotisation(models.Model): return True, None def can_view_all(user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)): + if not user_request.has_perm('cotisation.view_cotisation'): return False, u"Vous n'avez pas le droit de voir les cotisations" return True, None def can_view(self, user_request, *args, **kwargs): - if not user_request.has_perms(('cableur',)) and\ + if not user_request.has_perm('cotisation.view_cotisation') and\ self.vente.facture.user != user_request: return False, u"Vous ne pouvez pas afficher l'historique d'une\ cotisation d'un autre user que vous sans droit cableur" diff --git a/re2o/field_permissions.py b/re2o/field_permissions.py index 172f4f95..dc5466c4 100644 --- a/re2o/field_permissions.py +++ b/re2o/field_permissions.py @@ -9,9 +9,6 @@ class FieldPermissionModelMixin: FIELD_PERMISSION_GETTER = 'can_change_{name}' FIELD_PERMISSION_MISSING_DEFAULT = True - def has_perm(self, user, perm): - return user.has_perm(perm) # Never give 'obj' argument here - def has_field_perm(self, user, field): if field in self.field_permissions: checks = self.field_permissions[field] diff --git a/users/migrations/0061_auto_20171230_2033.py b/users/migrations/0061_auto_20171230_2033.py new file mode 100644 index 00000000..f2751fe2 --- /dev/null +++ b/users/migrations/0061_auto_20171230_2033.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-12-30 19:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ('users', '0060_auto_20171120_0317'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='groups', + field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'), + ), + migrations.AddField( + model_name='user', + name='is_superuser', + field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'), + ), + migrations.AddField( + model_name='user', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), + ), + ] diff --git a/users/models.py b/users/models.py index 5e852fd8..32326e5a 100644 --- a/users/models.py +++ b/users/models.py @@ -62,7 +62,8 @@ from django.db import transaction from django.utils import timezone from django.contrib.auth.models import ( AbstractBaseUser, - BaseUserManager + BaseUserManager, + PermissionsMixin ) from django.core.validators import RegexValidator @@ -181,7 +182,7 @@ class UserManager(BaseUserManager): """ return self._create_user(pseudo, surname, email, password, True) -class User(FieldPermissionModelMixin, AbstractBaseUser): +class User(FieldPermissionModelMixin, AbstractBaseUser, PermissionsMixin): """ Definition de l'utilisateur de base. Champs principaux : name, surnname, pseudo, email, room, password Herite du django BaseUser et du système d'auth django""" @@ -285,20 +286,7 @@ class User(FieldPermissionModelMixin, AbstractBaseUser): @property def is_admin(self): """ Renvoie si l'user est admin""" - try: - Right.objects.get(user=self, right__listright='admin') - except Right.DoesNotExist: - return False - return True - - @is_admin.setter - def is_admin(self, value): - """ Change la valeur de admin à true ou false suivant la valeur de - value""" - if value and not self.is_admin: - self.make_admin() - elif not value and self.is_admin: - self.un_admin() + return self.is_superuser def get_full_name(self): """ Renvoie le nom complet de l'user formaté nom/prénom""" @@ -312,66 +300,6 @@ class User(FieldPermissionModelMixin, AbstractBaseUser): """ Renvoie seulement le nom""" return self.surname - def has_perms(self, perms, obj=None): - """ Renvoie true si l'user dispose de la permission. - Prend en argument une liste de permissions. - TODO : Arranger cette fonction""" - for perm in perms: - if perm in RIGHTS_LINK: - query = Q() - for right in RIGHTS_LINK[perm]: - query = query | Q(right__listright=right) - if Right.objects.filter(Q(user=self) & query): - return True - try: - Right.objects.get(user=self, right__listright=perm) - except Right.DoesNotExist: - return False - return True - - def has_perm(self, perm, obj=None): - """Ne sert à rien""" - return True - - def has_right(self, right): - """ Renvoie si un user a un right donné. Crée le right si il n'existe - pas""" - try: - list_right = ListRight.objects.get(listright=right) - except: - list_right = ListRight(listright=right, gid=get_fresh_gid()) - list_right.save() - return Right.objects.filter(user=self).filter( - right=list_right - ).exists() - - @cached_property - def is_bureau(self): - """ True si user a les droits bureau """ - return self.has_right('bureau') - - @cached_property - def is_bofh(self): - """ True si l'user a les droits bofh""" - return self.has_right('bofh') - - @cached_property - def is_cableur(self): - """ True si l'user a les droits cableur - (également true si bureau, infra ou bofh)""" - return self.has_right('cableur') or self.has_right('bureau') or\ - self.has_right('infra') or self.has_right('bofh') - - @cached_property - def is_trez(self): - """ Renvoie true si droits trésorier pour l'user""" - return self.has_right('tresorier') - - @cached_property - def is_infra(self): - """ True si a les droits infra""" - return self.has_right('infra') - def end_adhesion(self): """ Renvoie la date de fin d'adhésion d'un user. Examine les objets cotisation"""