#36843 closed Bug (fixed)
RenamePermission might operate on unrelated models
| Reported by: | Jacob Walls | Owned by: | Jacob Walls |
|---|---|---|---|
| Component: | contrib.auth | Version: | 6.0 |
| Severity: | Release blocker | Keywords: | |
| Cc: | Artyom Kotovskiy | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
As of Django 6.0 (#27489), when a migration contains a RenameModel operation, ephemeral RenamePermission operations are injected to sync the name & codename of the model's permission records.
As mentioned in https://github.com/django/django/pull/20339#discussion_r2653481704, we discovered that the ephemeral operation might operate on unrelated models owing to its use of model__icontains:
ctypes = ContentType.objects.using(db).filter( app_label=self.app_label, model__icontains=old_model.lower() ) for permission in Permission.objects.using(db).filter( content_type_id__in=ctypes.values("id") ):
To reproduce:
- Have
SongandSongProfilemodels, migrate (this produces permission records duringpost_migrate) - assign a view permission on
SongProfileto a user - Rename
SongtoSon, migrate RenamePermissionadjusts the four permissions on each model (8 perms total) to all have "son" in the name & codename- Permissions are now missing for
SongProfile, so they get regenerated by the post_migrate handler - existing user/group assignments (e.g. the one created above) are now pointing to the wrong permission ("add_son" with a content type pointing to
SongProfile)
Unlike #36793, which hinged on the existence of stale records causing conflicts (possibly from reapplying or reversing migrations in environments that had stale permissions before Django 6), this scenario doesn't involve any duplicates, and the models in step 2 don't need to be the same as step 1, just have common substrings. I reused a model for convenience, but the point is that an unrelated model's permissions are being affected.
Suggesting to revert of f02b49d2f3bf84f5225de920ca510149f1f9f1da and that we address the issues identified in https://github.com/django/django/pull/20481 (which was a first pass at identifying & fixing) with more breathing room in a future version.
Change History (7)
comment:1 by , 40 hours ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:2 by , 40 hours ago
| Description: | modified (diff) |
|---|
comment:3 by , 39 hours ago
| Has patch: | set |
|---|
comment:4 by , 39 hours ago
| Triage Stage: | Unreviewed → Accepted |
|---|
I can confirm the described problem. After following the steps, I get:
django=# select * from django_content_type where model ilike '%son%'; id | app_label | model ----+-----------+------------- 60 | testapp | songprofile 59 | testapp | son (2 rows) django=# select * from auth_permission where content_type_id in (60, 59); id | name | content_type_id | codename -----+-------------------------+-----------------+-------------------- 233 | Can add son | 59 | add_son 234 | Can change son | 59 | change_son 235 | Can delete son | 59 | delete_son 236 | Can view son | 59 | view_son 237 | Can add son | 60 | add_son 238 | Can change son | 60 | change_son 239 | Can delete son | 60 | delete_son 240 | Can view son | 60 | view_son 241 | Can add song profile | 60 | add_songprofile 242 | Can change song profile | 60 | change_songprofile 243 | Can delete song profile | 60 | delete_songprofile 244 | Can view song profile | 60 | view_songprofile (12 rows)
And the user that originally got a view perm for songprofile, can now view son instances.
comment:5 by , 39 hours ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
PR to revert #27489