kopia lustrzana https://github.com/wagtail/wagtail
Add ordering for group editor object permissions
- Ensure the sorting will preserve Django's Permission model ordering as per ordering = ["content_type__app_label", "content_type__model", "codename"] - `ordering = ["content_type__app_label", "content_type__model", "codename"]` - Closes #10468pull/10595/head
rodzic
f5187d1938
commit
17230d183a
|
@ -11,6 +11,7 @@ Changelog
|
|||
* Add oEmbed provider patterns for YouTube Shorts Shorts and YouTube Live URLs (valnuro, Fabien Le Frapper)
|
||||
* Add initial implementation of `PagePermissionPolicy` (Sage Abdullah)
|
||||
* Refactor `UserPagePermissionsProxy` and `PagePermissionTester` to use `PagePermissionPolicy` (Sage Abdullah)
|
||||
* Add a predictable default ordering of the "Object/Other permissions" in the Group Editing view, allow this ordering to be customised (Daniel Kirkham)
|
||||
* Fix: Prevent choosers from failing when initial value is an unrecognised ID, e.g. when moving a page from a location where `parent_page_types` would disallow it (Dan Braghis)
|
||||
* Fix: Move comment notifications toggle to the comments side panel (Sage Abdullah)
|
||||
* Fix: Remove comment button on InlinePanel fields (Sage Abdullah)
|
||||
|
|
|
@ -106,3 +106,29 @@ INSTALLED_APPS = [
|
|||
...,
|
||||
]
|
||||
```
|
||||
|
||||
(customising_group_views_permissions_order)=
|
||||
|
||||
## Customising the group editor permissions ordering
|
||||
|
||||
The order that object types appear in the group editor's "Object permissions" and "Other permissions" sections can be configured by registering that order in one or more `AppConfig` definitions. The order value is typically an integer between 0 and 999, although this is not enforced.
|
||||
|
||||
```python
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MyProjectAdminAppConfig(AppConfig):
|
||||
name = "myproject_admin"
|
||||
verbose_name = "My Project Admin"
|
||||
|
||||
def ready(self):
|
||||
from wagtail.users.permission_order import register
|
||||
|
||||
register("gadgets.SprocketType", order=150)
|
||||
register("gadgets.ChainType", order=151)
|
||||
register("site_settings.Settings", order=160)
|
||||
```
|
||||
|
||||
A model class can also be passed to `register()`.
|
||||
|
||||
Any object types that are not explicitly given an order will be sorted in alphabetical order by `app_label` and `model`, and listed after all of the object types _with_ a configured order.
|
||||
|
|
|
@ -23,6 +23,7 @@ FieldPanels can now be marked as read-only with the `read_only=True` keyword arg
|
|||
* Add oEmbed provider patterns for YouTube Shorts (e.g. [https://www.youtube.com/shorts/nX84KctJtG0](https://www.youtube.com/shorts/nX84KctJtG0)) and YouTube Live URLs (valnuro, Fabien Le Frapper)
|
||||
* Add initial implementation of `PagePermissionPolicy` (Sage Abdullah)
|
||||
* Refactor `UserPagePermissionsProxy` and `PagePermissionTester` to use `PagePermissionPolicy` (Sage Abdullah)
|
||||
* Add a predictable default ordering of the "Object/Other permissions" in the Group Editing view, allow this [ordering to be customised](customising_group_views_permissions_order) (Daniel Kirkham)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -120,3 +121,10 @@ If you use the `user_page_permissions` context variable or use the `UserPagePerm
|
|||
The undocumented `get_pages_with_direct_explore_permission` and `get_explorable_root_page` functions in `wagtail.admin.navigation` are deprecated. They can be replaced with `PagePermissionPolicy().instances_with_direct_explore_permission(user)` and `PagePermissionPolicy().explorable_root_instance(user)`, respectively.
|
||||
|
||||
The undocumented `users_with_page_permission` function in `wagtail.admin.auth` is also deprecated. It can be replaced with `PagePermissionPolicy().users_with_permission_for_instance(action, page, include_superusers)`.
|
||||
|
||||
### The default ordering of Group Editing Permissions models has changed
|
||||
|
||||
The ordering for "Object permissions" and "Other permissions" now follows a predictable order equivalent do Django's default `Model` ordering.
|
||||
This will be different to the previous ordering which never intentionally implemented.
|
||||
|
||||
This default ordering is now `["content_type__app_label", "content_type__model", "codename"]`, which can now be customised [](customising_group_views_permissions_order).
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from wagtail.coreutils import resolve_model_string
|
||||
|
||||
CONTENT_TYPE_ORDER = {}
|
||||
|
||||
|
||||
def register(model, **kwargs):
|
||||
"""
|
||||
Registers order against the model content_type, used to
|
||||
control the order the models and its permissions appear
|
||||
in the groups object permission editor
|
||||
"""
|
||||
order = kwargs.pop("order", None)
|
||||
if order is not None:
|
||||
content_type = ContentType.objects.get_for_model(resolve_model_string(model))
|
||||
CONTENT_TYPE_ORDER[content_type.id] = order
|
|
@ -4,6 +4,7 @@ import re
|
|||
from django import template
|
||||
|
||||
from wagtail import hooks
|
||||
from wagtail.users.permission_order import CONTENT_TYPE_ORDER
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -38,8 +39,13 @@ def format_permissions(permission_bound_field):
|
|||
|
||||
"""
|
||||
permissions = permission_bound_field.field._queryset
|
||||
# get a distinct list of the content types that these permissions relate to
|
||||
content_type_ids = set(permissions.values_list("content_type_id", flat=True))
|
||||
# get a distinct and ordered list of the content types that these permissions relate to.
|
||||
# relies on Permission model default ordering, dict.fromkeys() retaining that order
|
||||
# from the queryset, and the stability of sorted().
|
||||
content_type_ids = sorted(
|
||||
dict.fromkeys(permissions.values_list("content_type_id", flat=True)),
|
||||
key=lambda ct: CONTENT_TYPE_ORDER.get(ct, float("inf")),
|
||||
)
|
||||
|
||||
# iterate over permission_bound_field to build a lookup of individual renderable
|
||||
# checkbox objects
|
||||
|
|
|
@ -24,6 +24,7 @@ from wagtail.models import (
|
|||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.users.forms import UserCreationForm, UserEditForm
|
||||
from wagtail.users.models import UserProfile
|
||||
from wagtail.users.permission_order import register as register_permission_order
|
||||
from wagtail.users.views.groups import GroupViewSet
|
||||
from wagtail.users.views.users import get_user_creation_form, get_user_edit_form
|
||||
from wagtail.users.wagtail_hooks import get_group_viewset_cls
|
||||
|
@ -1947,6 +1948,71 @@ class TestGroupEditView(WagtailTestUtils, TestCase):
|
|||
# Should not show inputs for publish permissions on models without DraftStateMixin
|
||||
self.assertNotInHTML("Can publish advert", html)
|
||||
|
||||
def test_group_edit_loads_with_django_permissions_in_order(self):
|
||||
# ensure objects are ordered as registered, followed by the default ordering
|
||||
|
||||
def object_position(object_perms):
|
||||
# returns the list of objects in the object permsissions
|
||||
# as provided by the format_permissions tag
|
||||
|
||||
def flatten(perm_set):
|
||||
# iterates through perm_set dict, flattens the list if present
|
||||
for v in perm_set.values():
|
||||
if isinstance(v, list):
|
||||
for e in v:
|
||||
yield e
|
||||
else:
|
||||
yield v
|
||||
|
||||
return [
|
||||
(
|
||||
perm.content_type.app_label,
|
||||
perm.content_type.model,
|
||||
)
|
||||
for perm_set in object_perms
|
||||
for perm in [next(v for v in flatten(perm_set) if "perm" in v)["perm"]]
|
||||
]
|
||||
|
||||
# Set order on two objects, should appear first and second
|
||||
register_permission_order("snippetstests.fancysnippet", order=100)
|
||||
register_permission_order("snippetstests.standardsnippet", order=110)
|
||||
|
||||
response = self.get()
|
||||
object_positions = object_position(response.context["object_perms"])
|
||||
self.assertEqual(
|
||||
object_positions[0],
|
||||
("snippetstests", "fancysnippet"),
|
||||
msg="Configured object permission order is incorrect",
|
||||
)
|
||||
self.assertEqual(
|
||||
object_positions[1],
|
||||
("snippetstests", "standardsnippet"),
|
||||
msg="Configured object permission order is incorrect",
|
||||
)
|
||||
|
||||
# Swap order of the objects
|
||||
register_permission_order("snippetstests.standardsnippet", order=90)
|
||||
response = self.get()
|
||||
object_positions = object_position(response.context["object_perms"])
|
||||
|
||||
self.assertEqual(
|
||||
object_positions[0],
|
||||
("snippetstests", "standardsnippet"),
|
||||
msg="Configured object permission order is incorrect",
|
||||
)
|
||||
self.assertEqual(
|
||||
object_positions[1],
|
||||
("snippetstests", "fancysnippet"),
|
||||
msg="Configured object permission order is incorrect",
|
||||
)
|
||||
|
||||
# Test remainder of objects are sorted
|
||||
self.assertEqual(
|
||||
object_positions[2:],
|
||||
sorted(object_positions[2:]),
|
||||
msg="Default object permission order is incorrect",
|
||||
)
|
||||
|
||||
|
||||
class TestGroupViewSet(TestCase):
|
||||
def setUp(self):
|
||||
|
|
Ładowanie…
Reference in New Issue