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

enhance admin integration #593

Open
wants to merge 4 commits into
base: devel
Choose a base branch
from

Conversation

lintingbin
Copy link

  1. only superuser to view the "Object permissions" button.
  2. overwrite has_module_permission, get_queryset, has_view_permission, has_change_permission, has_delete_permission function of the GuardedModelAdmin class.
  3. auto add obj permission to the user who create it.
  4. auto delete obj permission after obj be deleted.

lintingbin and others added 4 commits October 27, 2018 14:44
…ian into devel

# Conflicts:
#	guardian/locale/zh_Hans/LC_MESSAGES/django.mo
#	guardian/locale/zh_Hans/LC_MESSAGES/django.po
[remove_perm(perm, user_or_group, obj) for perm in perms_dict[user_or_group]]

def delete_model(self, request, obj):
self.remove_obj_perms(obj)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of Generic Foreign Key, such an operation is useful (as far as I know). However, in the case of Direct Foreign Key, it is responsible for the database, so there is no point in performing this operation.

I am afraid, however, why this operation is to be performed only when using the administration panel. Maybe we should register the listeners of the corresponding signals?

return super(GuardedModelAdmin, self).delete_model(request, obj)

def delete_queryset(self, request, queryset):
[self.remove_obj_perms(obj) for obj in queryset]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in previous comment, but in that situation I see clear way to integrate that in our Manager, so it will works to any delete operation, not only via Admin.

Copy link
Member

@ad-m ad-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the proposed patch. I am glad that you reported them in such a convenient form, which enabled me to analyze and comment carefully. Could you refer to my remarks and to make appropriate patch to ensure a comfortable use of the library by everyone?

perms_dict = get_users_with_perms(obj, attach_perms=True)
perms_dict.update(get_groups_with_perms(obj, attach_perms=True))
for user_or_group in perms_dict:
[remove_perm(perm, user_or_group, obj) for perm in perms_dict[user_or_group]]
Copy link
Member

@ad-m ad-m Nov 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We extract the code for "shortcuts" instead of static methods. This allows you to re-use the code.

You download the permissions (+1 query) to then delete the permission for each user (+n queries). Could you eliminate this and build the correct query that will do it all at once? Maybe we need to extend our shortcuts to handle that in easy way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When an obj is deleted, we need have an api to delete its permission. I think this api put to "shortcuts" is good.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update pull request to reflect that?

if not request.user.is_superuser and not change:
opts = self.opts
actions = ['view', 'add', 'change', 'delete']
[assign_perm('{}.{}_{}'.format(opts.app_label, action, opts.model_name), request.user, obj)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is transferring the internal logic of your application to the library, which should be deprived of such elements. Why do not you use signals for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that you need information about who created it. Usually, I stores such information in the object (createdBy field), so the signal listener have access to it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another way is make that list of permission_for_created_objs configurable by user and make empty by default.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this isn't the internal logic of my application, this function is the normal function that django-guardian need to provide when django-guardian be integrated with Admin.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term "internal logic" was not the best term. I see the field for improvement and after thinking it out I believe it is valuable to give permission to the user who created the resource. In my opinion, a persistent set of permissions is not suitable for library. This functionality may work, for example, without using "delete" permissions. This set of permissions can be the default.

return self.get_model_objs(request).exists()

def get_queryset(self, request):
if request.user.is_superuser:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, moving logic of your application to our library. Is there a shortcut to this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the impression that transferring logic, because in django-guardian, if there is a possibility, we do not abuse the superuser, and in fact we use permissions. Independently, I see the potential for change in this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is no problem. The superuser have the all permission, and "get_queryset" return all objs for superuser is correct.

@@ -2,7 +2,9 @@
{% load i18n admin_urls %}

{% block object-tools-items %}
{% if request.user.is_superuser %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can not accept that way to determine button visibility. It introduces a security risk because the button will have a different display logic from the page to which it directs. I agree that this should be uniform and this is currently an bug. However, we can not solve this in such a simplified way, because we lose flexibility. I rather see in that part reusing that condition: https://github.com/django-guardian/django-guardian/blob/devel/guardian/admin.py#L225
It is possible that this condition should be extracted to separate method, so the result of that method can be overwritten (extra flexibility for end user) and used in two places.

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

Successfully merging this pull request may close these issues.

None yet

2 participants