#30028 closed Bug (duplicate)
Uneditable object still editable through change_list if list_editable not empty
Reported by: | ksl | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | 2.1 |
Severity: | Normal | Keywords: | changelist |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Abstract
This bug allows an object that should be uneditable (its has_change_permission
method always returns False
) to be edited through an editable changelist.
Steps to reproduce
- Use the following admin:
class ArticleAdmin(models.ModelAdmin): list_display = ("title", "author", "abstract") list_editable = ("title", "author") def has_change_permission(self, request, obj=None): return False
- Navigate to the article changelist.
- Change any title/author field and save.
Result
The modified article objects are indeed modified and saved to database.
Expected result
The changelist view should (as does change form) display read-only fields (ie: span
s, not input
s), and disallow any modification to be saved to database.
Technical information
Tested on Django 2.1.4.
Attachments (2)
Change History (12)
comment:1 by , 6 years ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
comment:2 by , 6 years ago
Sorry, my bad.
The situation is actually more complex but boils down to the fact that has_change_permission
is called with obj=None
.
This does not allow individual objects (rows) in the changelist to be editable while others are not: either the whole changelist is editable or it's not. Or am I missing something here?
Edit:
The admin to reproduce this could be:
class ArticleAdmin(models.ModelAdmin): list_display = ("title", "author", "abstract") list_editable = ("title", "author") def has_change_permission(self, request, obj=None): if obj is not None: return obj.pk == 1
In such a case (which is closer to our actual use case), the Article object with ID 1 will not be editable through its changeform but would be through its changelist.
comment:3 by , 6 years ago
Can you put this into a project or a test case, so we can see it in action?
follow-up: 6 comment:4 by , 6 years ago
Happy to look at a project if you can provide one but just glancing at the code, it looks like a programming error: you’re going to need to look at the request.user
to see what you should return. Otherwise you’ve overridden the default implementation, which protects against this sort of thing.
You should probably be calling super()
before your own logic, and only continuing if that returns True
.
comment:6 by , 6 years ago
Replying to Carlton Gibson:
Happy to look at a project if you can provide one but just glancing at the code, it looks like a programming error: you’re going to need to look at the
request.user
to see what you should return. Otherwise you’ve overridden the default implementation, which protects against this sort of thing, and created the issue.
You should probably be calling
super()
before your own logic, and only continuing if that returnsTrue
.
Please find enclosed a test project reflecting our situation. In this project, the Question object with ID 1 should be the only one editable.
As you understand, our logic here is not based on per-user permission (hence we do not use request.user
nor do we call super()
) but on per-object permission.
Test project credentials:
- User
admin
with passwordadminadmin
- User
notadmin
with passwordadminadmin
comment:7 by , 6 years ago
Replying to Simon Charette:
That looks like a duplicate of #15759 to me.
Might be a duplicate indeed, except I'm not sure I understand the "if an auth backend supports per-object permissions." correctly.
In our case, it's a matter of "if an object's has_permission
returns False
".
comment:8 by , 6 years ago
Resolution: | worksforme → duplicate |
---|
Hi ksl
— Thanks for the follow-up.
Looks like Simon's right about it being a Duplicate of #15759. With the superuser all rows are shown as editable.
The view-only user behaviour looks correct though: No rows are shown as editable if the user can only view
the admin.
comment:9 by , 6 years ago
View-only user is actually the only one working as expected. Once you empower a user to change objects of the model, the has_change_permission
logic is somewhat bypassed (or at least does not allow a per-object logic).
Thank you, for taking precious time to answer.
comment:10 by , 6 years ago
No problem. Thank you for your report, and for the effort of making sure I followed properly. 🙂
I can't reproduce this.
list_editable
is working as expected.list_editable
fields are not presented as form widgets. (As expected.)has_change_permission()
to always returnFalse
I'm going to close as-is. If you can provide an example project reproducing this (perhaps with a frozen requirements files so we can see the exact Django version) I'm happy to look again.