Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 700
Lord_JABA Avatar asked Nov 01 '22 23:11

Lord_JABA


2 Answers

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.

like image 161
lukaszb Avatar answered Nov 13 '22 18:11

lukaszb


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)
like image 41
Lord_JABA Avatar answered Nov 13 '22 18:11

Lord_JABA