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

Respect can_read_model in DjangoModelPermissions #6325

Closed

Conversation

paultiplady
Copy link

Django version 2.1 introduced the can_read_model permission
to support read-only ModelAdmin views. Add support for this
permission to a DjangoModelPermissions subclass.

(A subclass is created in order to preserve
backwards-compatibility with versions of Django that don't
support this flag).

FIXES: #6324

TODO: design, tests.

@paultiplady
Copy link
Author

Two design options:

  1. Break backwards compatibility by updating the DjangoModelPermissions GET check to require the new permission. This has the advantage of being more secure by default, but the major disadvantage of breaking backwards compatibility.
  2. Create a new subclass with the stricter permissions check. Advantage is it maintains compatibility, disadvantage is more auth classes to document/test/maintain.

As a user that expected the default behaviour to be to not grant read access to all users, I prefer 1, but I'm not sure how painful you consider a back-incompatible change to be.

@tomchristie
Copy link
Member

I'd suggest (1) but only merging it with the next major version change.

@paultiplady paultiplady force-pushed the django-permissions-read-only branch 3 times, most recently from 8bd001d to e879e8c Compare November 19, 2018 17:00
Django version 2.1 introduced the `can_read_model` permission
to support read-only ModelAdmin views. Add support for this
permission to a DjangoModelPermissions subclass.

(A subclass is created in order to preserve
backwards-compatibility with versions of Django that don't
support this flag).
@paultiplady
Copy link
Author

Sounds good. I've updated the code with this approach. The tests are currently failing because this permission doesn't exist on older versions by default; wonder what the approach should be for testing this? Is there precedent elsewhere that I could compare/copy?

Might be able to do something like adding the view permission only in the new has_view_permission test, and skipping these tests if version < nextversion?

@rpkilby
Copy link
Member

rpkilby commented Nov 19, 2018

We plan on dropping Django 1.11 in April when the 2.2 LTS release is cut. This also coincides with the EOL for Django 2.0, meaning that the version differences won't matter since 2.1 will be the minimum supported version.

Basically, this PR will need to hang around until we're ready to prepare the next major DRF release.

Copy link
Member

@rpkilby rpkilby left a comment

Choose a reason for hiding this comment

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

This will also need updated docs.

Copy link
Member

@rpkilby rpkilby left a comment

Choose a reason for hiding this comment

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

Blocked until we drop Django 1.11 & 2.0 in ~April.

@paultiplady
Copy link
Author

Ah gotcha, that makes sense. Will hang tight on this changeset then.

@gregschmit
Copy link
Contributor

This is a welcome change.

@carltongibson carltongibson added this to the 3.10 Release milestone Dec 19, 2018
@rpkilby
Copy link
Member

rpkilby commented Jul 1, 2019

Moving this to 3.11, since we're not dropping Django 1.11 support until at least December.

@idoash4
Copy link

idoash4 commented Dec 31, 2019

I am using this change in my project(by overriding DjangoObjectPermissions and setting the .perms_map property).
It is working as intended when listing objects using ModelViewSet. However when trying to retrieve a single item from the same view I am getting "detail": "Not found." error. This doesn't happen when the user making the request is a superuser. Adding all permission to the non-superuser testing user hasn't solved this as well.
@paultiplady have you tested this case?
I have spent a few hours on it and can't find anything wrong with my environment.

@marcosox
Copy link

marcosox commented Jul 3, 2020

Hello, any update on the status of this feature?

@namoshizun
Copy link

Hoping to see progress on this MR... I am already using it in my code but still would be nice to see it goes into the DRF codebase.

@@ -151,7 +151,7 @@ class DjangoModelPermissions(BasePermission):
# Override this if you need to also provide 'view' permissions,
# or if you want to provide custom permission codes.
perms_map = {
'GET': [],
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': [],
'HEAD': [],

Choose a reason for hiding this comment

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

I think the view_* permission check should be applied to HEAD requests as well.

Sure, the body isn't returned but having access to content-length could leak information about the page. Also, having GET and HEAD return different status codes seems weird to me.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed. We'd want the same permission on HEAD requests, yup.

Also the "Override this if you need to also provide 'view' permissions" part of the comment can be dropped.

@nemesifier
Copy link
Contributor

Hey there, can anyone give an update on what is missing from this PR so that some of us who are using DRF in @openwisp may help out in case it's doable for us? We will implement our own solution for this anyway so maybe it's worth to help here instead.

@tomchristie
Copy link
Member

@nemesisdesign Have added a comment above on a small tweak that'd be needed. Happy to take that either on this PR, on against a new one.

@nemesifier
Copy link
Contributor

@nemesisdesign Have added a comment above on a small tweak that'd be needed. Happy to take that either on this PR, on against a new one.

Cool, what about the OPTIONS method?

@namoshizun
Copy link

It is indeed a very useful addition.... hope it gets merged into the next release. We have been using this implementation for a long while, but it feels awkward each time when I have to explain why DRF doesn't include this solution..

Copy link
Contributor

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

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

I guess that if a user has the change permissions but not the view permissions, they should still be able to view, for backward compatibility reasons, since it's not guaranteed that old apps have view permissions created and assigned to users.

@ManishShah120
Copy link
Contributor

I am using this change in my project(by overriding DjangoObjectPermissions and setting the .perms_map property).
It is working as intended when listing objects using ModelViewSet. However when trying to retrieve a single item from the same view I am getting "detail": "Not found." error. This doesn't happen when the user making the request is a superuser. Adding all permission to the non-superuser testing user hasn't solved this as well.
@paultiplady have you tested this case?
I have spent a few hours on it and can't find anything wrong with my environment.

Hi, @BlackXnt Yes there's an issue with this PR, I have opened #8009 to deal with this case, you can do a similar thing and see if it resolves your problem. 👍

@nemesifier
Copy link
Contributor

#8009 is based on work we're doing in OpenWISP: openwisp/openwisp-users#251. Would be great to see this handled directly in DRF. Let us know if it needs improvement. We'll put effort in helping out on this (me, @ManishShah120 and @atb00ker).

@tomchristie tomchristie modified the milestones: 3.13 Release, 3.14 Jan 10, 2022
@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 16, 2022
@auvipy auvipy removed the stale label Jan 12, 2023
Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

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

closing in favor of #6325

@auvipy auvipy removed this from the 3.15 milestone Jan 12, 2023
@auvipy auvipy closed this Jan 12, 2023
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.

DjangoModelPermissions does not respect Django can_read_model permissoin