Django-guardian: Ajouter/Supprimer un membre uniquement pour un groupe spécifique

Créé le 20 nov. 2017  ·  35Commentaires  ·  Source: django-guardian/django-guardian

Bonjour, j'ai besoin d'une autorisation permettant aux utilisateurs d'un groupe spécifique d'ajouter, de supprimer ou de supprimer uniquement pour le groupe d'appartenance.

Tous les 35 commentaires

Pas de problème, vous devez créer de telles autorisations et implémenter manuellement le contrôle d'accès avec le support django-guardian.

Contrôle d'accès comme ?

Comment puis-je implémenter cette fonctionnalité ?

Django-guardian est une bibliothèque de contrôle d'accès pour tout objet. Un tel objet peut également être des groupes. Voir contrôle d'accès dans l'exemple de projet. Voir https://github.com/django-guardian/django-guardian/blob/devel/example_project/articles/views.py#L35 .

Parfait!

Voici mon extrait de code :

def create_user_profile(sender, instance, created, **kwargs):
    print("create_user_profile")
    try:
        print("created: "+ str(created))
        if created:
            Profile.objects.create(user=instance)
            print("Member.objects.get_or_create(django_user=instance)")
            #Create a user into groups_manager_member
            member = Member.objects.create(django_user=instance, first_name=instance.first_name, last_name=instance.last_name, username=instance.username, email=instance.email)
            print("member instance created")
            print(member)
            print("Group.objects.create(name=ID_GROUP+instance.username)")

            #Create a group into groups_manager_group
            group = Group.objects.create(name=ID_GROUP+instance.username)
            print("group instance created")
            print(group)
            #Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")

    except Exception as e:
        print("Exception: "+str(e))
        pass


def save_user_profile(sender, instance, **kwargs):
    print("save_user_profile")
    try:
        instance.profile.save()

    except Exception as e:
        print("Exception: "+str(e))
        pass

post_save.connect(create_user_profile, sender=User)
post_save.connect(save_user_profile, sender=User)

Je dois avoir la permission d'ajouter/supprimer pour tous les utilisateurs du groupe.

Je ne sais pas où avez-vous un problème. Vous avez besoin de quelque chose comme :

class ProtectedGroupUpdateView(PermissionRequiredMixin, GroupUpdateView):
    permission_required = ['change_group', ]
    ...

et attribuez l'autorisation au groupe lors de sa création.

J'ai essayé d'ajouter l'autorisation "peut ajouter un membre", mais c'est donc possible pour tous les groupes et non pour le personnel.

Je ne sais pas ce que vous voulez dire. Les privilèges django-guardian sont toujours accordés aux utilisateurs ou groupes d'utilisateurs. Il n'est pas possible d'accorder des privilèges en fonction du rôle ou des conditions particulières. Si vous souhaitez accorder aux membres du personnel l'autorisation de gérer le groupe "X", créez un groupe "Personnel", ajoutez-y des membres du personnel, ajoutez le groupe "X" et donnez au groupe "Personnel" l'autorisation de gérer "X" grouper.

J'aurais besoin d'un utilisateur qui appartient à un groupe
"X" ne peut ajouter ou supprimer que pour le groupe "X", malheureusement maintenant ce n'est pas le cas si vous avez la permission "vous pouvez ajouter des utilisateurs" pouvez le faire pour tous les groupes et non celui d'apprenti.

Désolé pour mon mauvais anglais

Malheureusement, je ne comprends pas vos attentes. Examinez attentivement l'exemple de projet . Cela devrait être suffisant dans un tel cas.

"X" can add or remove only for group "X" signifie :

  1. créer le groupe X,
  2. ajouter des membres du groupe X
  3. attribuer au groupe X l'autorisation de gérer le groupe X.

Je dois en fait m'assurer qu'un utilisateur appartenant à un groupe "x" puisse ajouter ou supprimer uniquement d'autres utilisateurs de son propre groupe

@Allan-Nava , Les privilèges django-guardian sont toujours accordés aux utilisateurs ou groupes d'utilisateurs. Il n'est pas possible d'accorder des privilèges en fonction du rôle ou des conditions particulières. Si vous souhaitez que les utilisateurs gèrent leurs groupes, donnez au groupe l'autorisation de gérer ce groupe en tant qu'objet.

Comprenez-vous comment attribuer et vérifier l'autorisation du groupe « X » pour gérer le groupe « X » ?

Cela devrait être comme netflix (mais tous les membres ont la possibilité de se connecter): chaque utilisateur devrait avoir un groupe personnel où il peut ajouter ou supprimer des utilisateurs selon ce qu'il préfère. Le problème est que si vous donnez cette autorisation, ajoutez des utilisateurs, et cela influence tous les autres groupes, pas les utilisateurs qui appartiennent à celui-ci

Le problème est que si vous donnez cette autorisation, ajoutez des utilisateurs, et cela influence tous les autres groupes, pas les utilisateurs qui appartiennent à celui-ci

Ce n'est certainement pas vrai. Cette phrase est vraie pour le noyau Django. Si vous utilisez l'autorisation Django-guardian correcte accordée au groupe de gestion X pour le groupe X, s'applique uniquement au groupe X. Tout comme dans un exemple de projet, donner le droit de gérer un article particulier ne signifie pas que d'autres articles peuvent être modifiés par cet utilisateur.

Je souhaite créer une autorisation unique qui permet à tous les utilisateurs d'ajouter d'autres personnes à leur groupe de membres. Chaque fois que je crée un nouvel utilisateur, avec son groupe d'appartenance « X », je veux qu'une nouvelle autorisation soit créée, appelée « Peut ajouter un groupe pour X », et cette autorisation doit avoir le groupe « X » comme objet.

Comme ça:

def create_user_profile(sender, instance, created, **kwargs):
    print("create_user_profile")
    try:
        print("created: "+ str(created))
        if created:
            Profile.objects.create(user=instance)
            print("Member.objects.get_or_create(django_user=instance)")
            #Create a user into groups_manager_member
            member = Member.objects.create(django_user=instance, first_name=instance.first_name, last_name=instance.last_name, username=instance.username, email=instance.email)
            print("member instance created")
            print(member)
            print("Group.objects.create(name=ID_GROUP+instance.username)")

            #Create a group into groups_manager_group
            group = Group.objects.create(name=ID_GROUP+instance.username)
            print("group instance created")
            print(group)
            #Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")
            UserObjectPermission.objects.assign_perm('can_add_member_for_xgroup', member, obj=group)

    except Exception as e:
        print("Exception: "+str(e))
        pass


def save_user_profile(sender, instance, **kwargs):
    print("save_user_profile")
    try:
        instance.profile.save()

    except Exception as e:
        print("Exception: "+str(e))
        pass

post_save.connect(create_user_profile, sender=User)
post_save.connect(save_user_profile, sender=User)



Anormal est la création de mille autorisations. assign_perm('manage_group',group,group) ou assign_perm('manage_group',user,group) cela devrait suffire. Le reste consiste à valider si l'utilisateur a l'autorité pour gérer un groupe particulier.

Ok parfait, mais dans la vue templare comment puis-je vérifier ?

{{ perms.groups_manager.canaddmemberx2}}

@Allan-Nava , encore une fois, examinez attentivement l'exemple de projet, en particulier les modèles et RTFD .

@ad-m Ok merci, donc mon extrait de code :

from guardian.shortcuts import assign_perm

def create_user_profile(sender, instance, created, **kwargs):
    print("create_user_profile")
    try:
        print("created: "+ str(created))
        if created:
            Profile.objects.create(user=instance)
            print("Member.objects.get_or_create(django_user=instance)")
            #Create a user into groups_manager_member
            member = Member.objects.create(django_user=instance, first_name=instance.first_name, last_name=instance.last_name, username=instance.username, email=instance.email)
            print("member instance created")
            print(member)
            print("Group.objects.create(name=ID_GROUP+instance.username)")

            #Create a group into groups_manager_group
            group = Group.objects.create(name=ID_GROUP+instance.username)
            print("group instance created")
            print(group)
            #Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")
            #UserObjectPermission.objects.assign_perm('can_add_member_for_xgroup', member, obj=group)
            assign_perm('groups_manager.can_add_member_custom', member, group)

    except Exception as e:
        print("Exception: "+str(e))
        pass


def save_user_profile(sender, instance, **kwargs):
    print("save_user_profile")
    try:
        instance.profile.save()

    except Exception as e:
        print("Exception: "+str(e))
        pass

post_save.connect(create_user_profile, sender=User)
post_save.connect(save_user_profile, sender=User)

@ad-m J'ai essayé ce code, mais j'ai eu une exception.

#Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")

            #Assign permission for the groups
            assign_perm('groups_manager.can_add_member_custom', member, group)
            print("assign_perm('groups_manager.can_add_member_custom', member, group)")

screen shot 2017-11-21 at 10 14 30

@Allan-Nava , qu'est-ce qui n'est pas clair pour vous dans le message d'erreur ?

@ad-m
J'ai ce bug :

def create_user_profile(sender, instance, created, **kwargs):
    print("create_user_profile")
    try:
        print("created: "+ str(created))
        if created:
            Profile.objects.create(user=instance)
            print("Member.objects.get_or_create(django_user=instance)")
            #Create a user into groups_manager_member
            member = Member.objects.create(django_user=instance, first_name=instance.first_name, last_name=instance.last_name, username=instance.username, email=instance.email)
            print("member instance created")
            print(member)
            print("Group.objects.create(name=ID_GROUP+instance.username)")

            #Create a group into groups_manager_group
            group = Group.objects.create(name=ID_GROUP+instance.username)
            print("group instance created")
            print(group)
            #Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")

            #Assign permission for the groups
            assign_perm('groups_manager.can_add_member_custom', instance, group)
            print("assign_perm('groups_manager.can_add_member_custom', instance, group)")

    except Exception as e:
        print("Exception: "+str(e))
        pass

screen shot 2017-11-21 at 12 53 38

@Allan-Nava , qu'est-ce qui n'est pas clair pour vous dans le message d'erreur ?

@ad-m je ne comprends pas où est le problème

@Allan-Nava , il n'y a pas ce genre d'autorisation. Lisez la doc quelle autorisation existe .

Ok, j'ai lu, mais j'ai besoin de créer N autorisation pour N groupes/utilisateurs lorsque je crée un nouvel utilisateur ?

content_type = ContentType.objects.get_for_model(Group)
permission = Permission.objects.create(
    codename='can_add_member_custom',
    name='Can Add Member Custom',
    content_type=content_type,
)

Comme dit précédemment :

Anormal est la création de mille autorisations.

Une autorisation par type d'action.

Comme dit avant :
Anormal est la création de mille autorisations.
Une autorisation par type d'action.

D'accord, mais comment puis-je créer l'autorisation générale ?

Comme le dit la documentation de base de Django. Lié ci-dessus.

D'accord, j'utilise Django Groups Manager :

C'est mon groupe modèle :

class Group(GroupMixin):

    group_type = models.ForeignKey(GroupType, null=True, blank=True, on_delete=models.SET_NULL,
                                   related_name='%(app_label)s_%(class)s_set')
    group_entities = models.ManyToManyField(GroupEntity, blank=True,
                                            related_name='%(app_label)s_%(class)s_set')

    django_group = models.ForeignKey(DjangoGroup, null=True, blank=True, on_delete=models.SET_NULL)
    group_members = models.ManyToManyField(Member, through='GroupMember',
                                           related_name='%(app_label)s_%(class)s_set')

    # this is just required for easy explanation
    class Meta(GroupMixin.Meta):
        abstract = False
        permissions = (
            ('can_add_member_custom', 'Can Add Member Custom'),
        )

Et voici mon profil de modèle :

from __future__ import unicode_literals

import hashlib
import os.path
import urllib

from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.utils.encoding import python_2_unicode_compatible

from bootcamp.activities.models import Notification
#Custom class - ParentsProfile
from bootcamp.parents.models import ParentsProfile
#Custom class - MemberMixin TO CREATE INTO groups_manager_member
from bootcamp.groups_manager.models import MemberMixin, Member, Group
#Import django guardian assign_perm
from guardian.shortcuts import assign_perm
#import UserObjectPermission
from guardian.models import UserObjectPermission

import datetime

ID_GROUP = "Group_"

'''
User Model - Authentication
'''
<strong i="12">@python_2_unicode_compatible</strong>
class Profile(models.Model):
    user = models.OneToOneField(User)
    location = models.CharField(max_length=50, null=True, blank=True)
    url = models.CharField(max_length=50, null=True, blank=True)
    job_title = models.CharField(max_length=50, null=True, blank=True)

    #I need to delete the parents application

    #Other tascout attributes
    birthdate = models.DateField(default=datetime.date.today)
    address = models.CharField(max_length=255, null=True, blank=True)
    main_role = models.CharField(max_length=255, null=True, blank=True)
    other_roles = models.CharField(max_length=255, null=True, blank=True)
    mobile = models.CharField(max_length=255, null=True, blank=True)
    background_photo = models.CharField(max_length=255, null=True, blank=True)
    profile_photo = models.CharField(max_length=255, null=True, blank=True)
    biography = models.TextField(null=True, blank=True)
    idols = models.TextField(null=True, blank=True)
    weight = models.IntegerField(default=0)
    height = models.IntegerField(default=0)
    favorite_team = models.CharField(max_length=255, null=True, blank=True)
    level = models.IntegerField(default=0)
    sex = models.CharField(max_length=1, default="M")
    nationality = models.CharField(max_length=255, null=True, blank=True)
    city = models.CharField(max_length=255, null=True, blank=True)
    postal_code = models.CharField(max_length=255, null=True, blank=True)
    province = models.CharField(max_length=255, null=True, blank=True)
    number = models.CharField(max_length=255, null=True, blank=True)
    latitude = models.DecimalField( null=True, blank=True, max_digits=9, decimal_places=6)
    longitude = models.DecimalField( null=True, blank=True, max_digits=9, decimal_places=6)

    class Meta:
        db_table = 'auth_profile'

    def __str__(self):
        return self.user.username

    def get_url(self):
        url = self.url
        if "http://" not in self.url and "https://" not in self.url and len(self.url) > 0:  # noqa: E501
            url = "http://" + str(self.url)

        return url

    def get_picture(self):
        no_picture = settings.MEDIA_URL +'/profile_pictures/user.png'
        try:
            filename = settings.MEDIA_ROOT + '/profile_pictures/' +\
                self.user.username + '.jpg'
            picture_url = settings.MEDIA_URL + 'profile_pictures/' +\
                self.user.username + '.jpg'
            if os.path.isfile(filename):  # pragma: no cover
                return picture_url
            else:  # pragma: no cover
                gravatar_url = 'http://www.gravatar.com/avatar/{0}?{1}'.format(
                    hashlib.md5(self.user.email.lower()).hexdigest(),
                    urllib.urlencode({'d': no_picture, 's': '256'})
                    )
                return gravatar_url

        except Exception:
            return no_picture

    #Retrieve users' cover
    def get_cover(self):
        no_cover = settings.MEDIA_ROOT +'profile_covers/cover.jpg'
        try:
            filename = settings.MEDIA_ROOT + '/profile_covers/' +\
                self.user.username + '.jpg'
            cover_url = settings.MEDIA_URL + 'profile_covers/' +\
                self.user.username + '.jpg'
            if os.path.isfile(filename) and os.path.exists(filename):  # pragma: no cover
                if cover_url != None:
                    return cover_url
                else:
                    return no_cover
            else:
                no_cover
        except Exception:
            return no_cover

    def get_screen_name(self):
        try:
            if self.user.get_full_name():
                return self.user.get_full_name()
            else:
                return self.user.username
        except:
            return self.user.username

    def notify_liked(self, feed):
        if self.user != feed.user:
            Notification(notification_type=Notification.LIKED,
                         from_user=self.user, to_user=feed.user,
                         feed=feed).save()

    def unotify_liked(self, feed):
        if self.user != feed.user:
            Notification.objects.filter(notification_type=Notification.LIKED,
                                        from_user=self.user, to_user=feed.user,
                                        feed=feed).delete()

    def notify_commented(self, feed):
        if self.user != feed.user:
            Notification(notification_type=Notification.COMMENTED,
                         from_user=self.user, to_user=feed.user,
                         feed=feed).save()

    def notify_also_commented(self, feed):
        comments = feed.get_comments()
        users = []
        for comment in comments:
            if comment.user != self.user and comment.user != feed.user:
                users.append(comment.user.pk)

        users = list(set(users))
        for user in users:
            Notification(notification_type=Notification.ALSO_COMMENTED,
                         from_user=self.user,
                         to_user=User(id=user), feed=feed).save()

    def notify_favorited(self, question):
        if self.user != question.user:
            Notification(notification_type=Notification.FAVORITED,
                         from_user=self.user, to_user=question.user,
                         question=question).save()

    def unotify_favorited(self, question):
        if self.user != question.user:
            Notification.objects.filter(
                notification_type=Notification.FAVORITED,
                from_user=self.user,
                to_user=question.user,
                question=question).delete()

    def notify_answered(self, question):
        if self.user != question.user:
            Notification(notification_type=Notification.ANSWERED,
                         from_user=self.user,
                         to_user=question.user,
                         question=question).save()

    def notify_accepted(self, answer):
        if self.user != answer.user:
            Notification(notification_type=Notification.ACCEPTED_ANSWER,
                         from_user=self.user,
                         to_user=answer.user,
                         answer=answer).save()

    def unotify_accepted(self, answer):
        if self.user != answer.user:
            Notification.objects.filter(
                notification_type=Notification.ACCEPTED_ANSWER,
                from_user=self.user,
                to_user=answer.user,
                answer=answer).delete()

def create_user_profile(sender, instance, created, **kwargs):
    print("create_user_profile")
    try:
        print("created: "+ str(created))
        if created:
            Profile.objects.create(user=instance)
            print("Member.objects.get_or_create(django_user=instance)")
            #Create a user into groups_manager_member
            member = Member.objects.create(django_user=instance, first_name=instance.first_name, last_name=instance.last_name, username=instance.username, email=instance.email)
            print("member instance created")
            print(member)
            print("Group.objects.create(name=ID_GROUP+instance.username)")

            #Create a group into groups_manager_group
            group = Group.objects.create(name=ID_GROUP+instance.username)
            print("group instance created")
            print(group)
            #Add member into the group correct
            group.add_member(member=member)
            print("member added into the group correct")

            #Assign permission for the groups
            assign_perm('can_add_member_custom', instance, group)
            #print("assign_perm('can_add_member_custom', instance, group)")

    except Exception as e:
        print("Exception: "+str(e))
        pass


def save_user_profile(sender, instance, **kwargs):
    print("save_user_profile")
    try:
        instance.profile.save()

    except Exception as e:
        print("Exception: "+str(e))
        pass

post_save.connect(create_user_profile, sender=User)
post_save.connect(save_user_profile, sender=User)

Django-guardian est une gestion des autorisations par objet unique, accordez donc une autorisation utilisateur/groupe unique à un seul objet.

Ok parfait, mais ne fonctionne toujours pas bien que j'ai ajouté l'autorisation dans le groupe de modèles

Qu'est-ce qui ne marche pas ?

Cette ligne:

#Assign permission for the groups
            assign_perm('can_add_member_custom', instance, group)
            print("assign_perm('can_add_member_custom', instance, group)")

l'instance est l' objet utilisateur mais j'ajoute dans le modèle de groupe l'autorisation

# this is just required for easy explanation
    class Meta(GroupMixin.Meta):
        abstract = False
        permissions = (
            ('can_add_member_custom', 'Can Add Member Custom'),
        )

J'ai utilisé ce django-groups-manager

Je suis stupide, je dois faire des migrations et migrer :

python3 manage.py makemigrations
python3 manage.py migrate

Merci de votre patience @ad-m

Mais dans la vue modèle, comment puis-je vérifier ?
cette:
jack.has_perm('change_group', admins)

Avec Django Shell ça marche :
screen shot 2017-11-21 at 16 42 17

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

BenDevelopment picture BenDevelopment  ·  5Commentaires

g-as picture g-as  ·  10Commentaires

xuhcc picture xuhcc  ·  10Commentaires

brianmay picture brianmay  ·  16Commentaires

Allan-Nava picture Allan-Nava  ·  4Commentaires