Lord_JABA
Lord_JABA

Reputation: 2625

django-guardian how to make object inherit permissions of related object?

I got two models:

class ContactGroup(models.Model):
    name = models.CharField(max_length=40)
    class Meta:
        permissions=(('view_group_contacts', 'View contacts from group'))


class Contact(models.Model):
    name = models.CharField(max_length=40)
    group = models.ForeignKey(ContactGroup)
    class Meta:
        permissions=(('view_contact', 'View contact'))        

How can I make django guardian consider ContactGroup permissions when I'm for example doing `get_objects_for_user(User, 'appname.view_contact) but still retain option for changing permission on individual Contact?(not for excluding, only to give permission to view single contact when user don't have the permission for whole group)

Upvotes: 6

Views: 1746

Answers (2)

Lord_JABA
Lord_JABA

Reputation: 2625

Very ugly workaround, it does not take for account changes in individual objects (it resets all permission to ContactGroup permissions if remove= False). But It can be rewritten to preserve changes if needed. I plan to attach it to "Sync Permissions with group" button so it will be fired only at user request. Main pro is its working with get_objects_for_user as intended.

def syncPerms(source, remove=False):
if not isinstance(source, ContactGroup):
    return False

contacts= source.client_set.all()
user_perms=get_users_with_perms(source, attach_perms=True)
for contact in contacts:
    for user, perm in user_perms.iteritems():
        if u'view_group_contacts' in perm:
            assign_perm('view_contact', user,client)
        else:
            if remove:
                remove_perm('view_contact', user, client)

Upvotes: 2

lukaszb
lukaszb

Reputation: 689

Sorry, such behaviour is not supported by django-guardian. As for has_perm - it would be extremely inefficient to use it for querysets as we would need to perform >=1 query for each row in a table.

You could however perform get_objects_for_user firstly for ContactGroup, then for Contact and extend last queryset with results from the first one. Something like:

contact_groups = get_objects_for_user(user, 'appname.view_group_contacts', ContactGroup)
contacts = get_objects_for_user(user, 'appname.view_contact', Contact)

There is still problem of merging those but well, it's possible.

Upvotes: 2

Related Questions