Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assign permission to any object of a type #766

Open
NaturalBornCamper opened this issue Nov 25, 2021 · 6 comments
Open

Assign permission to any object of a type #766

NaturalBornCamper opened this issue Nov 25, 2021 · 6 comments

Comments

@NaturalBornCamper
Copy link

NaturalBornCamper commented Nov 25, 2021

I'm trying to make an "admin" group with django-guardian that has access to all objects of a type instead of a single object, like such:

from guardian.models import UserObjectPermission
from django.contrib.contenttypes.models import ContentType
from apps.myapp.models import Website

# Create groups that can edit websites (admin can edit every website, the other group only a specific website)
admins = Group.objects.create(name='admins')
website_44_editors = Group.objects.create(name='website_44_editors')

# This works, assigning permission to edit website 44 to the correct group
website_44 = Website.objects.get(pk=44)
UserObjectPermission.objects.assign_perm('change_website', website_44_editors, obj=website_44)
website_44_editors.has_perm('change_website', website_44)

####### This doesn't work, as an object is needed #######
UserObjectPermission.objects.assign_perm('change_website', admins)
# Thus, this would also work, without admins having permission on specific website
admins.has_perm('change_website', website_44)

Any way to do this? Or is this the wrong approach and there is another way of doing this?

@ad-m
Copy link
Member

ad-m commented Nov 28, 2021

What do you want is not object-level permission, but model-level permission. Model-level permission is build-in in Django, so you do not need Django-guardian for that. If you really want to use django-guardian you might use it like that:

from guardian.shortcuts import assign_perm
assign_perm('articles.view_article', user, obj=None)

If you think that the issue has been resolved - please close it.

@NaturalBornCamper
Copy link
Author

NaturalBornCamper commented Nov 29, 2021

I think I really need object-level permission. Because

  • a Website with id 44 would be available to all users in the group website_44_editors
  • a Website with id 56 would be available to all users in the group website_56_editors
  • a Website with ANY id would be available to all users in the group admins

Furthermore, to see if a user has access to edit a certain Article for example, we check if that user has permission to edit the Website this Article is attached to (article.website.id =44, so we simply check if user has access to that website).

All we need is to check if a user has access to a Website, nothing else. Then from this, it can do anything to any model related to this Website

@ociule
Copy link

ociule commented Nov 29, 2021

Regarding this requirement, ad-m means it will work using assign_perm or you can do it through the admin site by adding the articles.view_website perm to the admin group:

####### This doesn't work, as an object is needed #######
UserObjectPermission.objects.assign_perm('change_website', admins)

# This will work using assign_perm
from guardian.shortcuts import assign_perm
assign_perm('articles.view_website', admins, obj=None)

I think you need the app name as a prefix in the permission, btw.

And indeed, for the rest you need row-level permissions. Especially for " if a user has access to edit a certain Article for example, we check if that user has permission to edit the Website this Article is attached to" - this is easy to do in view code:

request.user.has_perm('articles.view_website", article.website)

The same seems more complex to do in the admin site - anyone that knows how please share.

@ociule
Copy link

ociule commented Nov 30, 2021

I've managed to integrate guardian per row permission checking into the admin site. Admin list and change views now work as expected: a staff user can view and change rows for which he's been granted the permission. The per model classic Django permissions still work as before.

@ad-m would you be interested in a patch containing a PerRowPermissionCheckerModelAdminMixin and an update to the documentation page (https://django-guardian.readthedocs.io/en/stable/userguide/admin-integration.html) explaining how to use it ? There are multiple open issues asking how to check per row perms in admin, this would solve them. See also #761

@ad-m
Copy link
Member

ad-m commented Dec 5, 2021

I'm not interested in making such contributions to the project personally as I don't use django-guardian actively (see #759). I participate in this project sporadically when I receive a notification as there are no enought people in the project (see #603).

After you have properly granted the permissions, you can override the get_queryset method of ModelAdmin ( https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset ) to filter the objects ( guardian.shortcuts.get_objects_for_user). It is essential if you want to take global permissions into account, as was my previous comment, to use accept_global_perms for get_objects_for_user properly. I think that it is also worth learning about other parameters of this function in order to adapt them to the needs of your application. I would recommend that this logic be abstracted into your own custom manager of model with the for_user method to maintain ease of consistency between the admin panel and the basic views (example https://github.com/watchdogpolska/feder/blob/bfa25cc72b3e797d49dcf420638307413011fb2a/feder/letters/models.py#L370-L375 ).

@ociule
Copy link

ociule commented Dec 6, 2021

@ad-m I propose writing the MR and you'd have to review it and merge it. Will that work for you ?

Thanks for the suggestion for accept_global_perms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants