Search code examples
pythondjangodjango-guardian

In Django guardian, how can I determine which group gave the user permissions to the object instance?


I am trying to set up object-level permissions using Django guardian and groups; where I give permissions to the groups - not the users - and add/remove users from the groups as required.

When a user has permission to interact with an object instance - because they are in a group that has the necessary permissions - how can I determine which of the user's groups gave them the permission?

As an example, building off the example in the django-guardian-docs , ideally there would be something like:

>>> joe.has_perm_from_groups('sites.change_site', site)
[site_owners_group]

Solution

  • Django guardian has a shortcut called get_groups_with_perms(obj) that Returns queryset of all Group objects with any object permissions for the given obj. https://django-guardian.readthedocs.io/en/stable/api/guardian.shortcuts.html#get-groups-with-perms

    Django has a queryset method called intersection that returns the shared elements of two or more QuerySets https://docs.djangoproject.com/en/3.2/ref/models/querysets/#intersection

    Using these two functions, I can find the groups that the user is in that also have permissions for the object. I then use a for loop to identify the group with the permission. If two groups have the permission, I don't know how I would work out which one gave the user the permission, so the first group found is returned.

    # Find the union of groups
    groups = user.groups.all().intersection(get_groups_with_perms(obj))
    
    # Check if any group has the permission, and return if True
    for group in groups:
        if 'change_site' in get_perms(group, obj):
            return group
    return None