Skip to content

Commit 2d49477

Browse files
committed
fix #7672: Improve UX for PermissionAdmin
fix #7672: Improve UX for PermissionAdmin fix #7672: Improve UX for PermissionAdmin
1 parent 160669e commit 2d49477

File tree

2 files changed

+58
-77
lines changed

2 files changed

+58
-77
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Features:
1717
* Python 3.11, 3.10 support
1818
* Remove patching of PageContent by djangocms-versioning (#7446)
1919
* Utility function get_placeholder_from_slot for PlaceholderRelationField (#7479)
20+
* Use autocomplete for entities from model `User` and `Group` instead of the raw primary key.
2021

2122
Bug Fixes:
2223
----------

cms/admin/permissionadmin.py

Lines changed: 57 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,26 @@
1-
from copy import deepcopy
2-
31
from django.contrib import admin
4-
from django.contrib.admin import site
52
from django.contrib.auth import get_user_model
3+
from django.contrib.auth.models import Group
64
from django.contrib.auth.admin import UserAdmin
75
from django.contrib.sites.models import Site
8-
from django.db import OperationalError
96
from django.utils.translation import gettext_lazy as _
107

11-
from cms.admin.forms import (
12-
GlobalPagePermissionAdminForm,
13-
PagePermissionInlineAdminForm,
14-
ViewRestrictionInlineAdminForm,
15-
)
168
from cms.exceptions import NoPermissionsException
179
from cms.models import GlobalPagePermission, PagePermission
1810
from cms.utils import page_permissions, permissions
1911
from cms.utils.conf import get_cms_setting
20-
from cms.utils.helpers import classproperty
12+
from cms.utils.permissions import get_subordinate_users, get_subordinate_groups
2113

2214
PERMISSION_ADMIN_INLINES = []
2315

2416
user_model = get_user_model()
2517
admin_class = UserAdmin
26-
for model, admin_instance in site._registry.items():
18+
for model, admin_instance in admin.site._registry.items():
2719
if model == user_model:
2820
admin_class = admin_instance.__class__
2921

3022

31-
class TabularInline(admin.TabularInline):
32-
pass
33-
34-
35-
class PagePermissionInlineAdmin(TabularInline):
36-
model = PagePermission
37-
# use special form, so we can override of user and group field
38-
form = PagePermissionInlineAdminForm
39-
extra = 0 # edit page load time boost
40-
show_with_view_permissions = False
41-
23+
class PagePermissionAdminMixin:
4224
def has_change_permission(self, request, obj=None):
4325
if not obj:
4426
return False
@@ -51,38 +33,45 @@ def has_change_permission(self, request, obj=None):
5133
def has_add_permission(self, request, obj=None):
5234
return self.has_change_permission(request, obj)
5335

54-
@classproperty
55-
def raw_id_fields(cls):
56-
# Dynamically set raw_id_fields based on settings
57-
threshold = get_cms_setting('RAW_ID_USERS')
58-
59-
# Given a fresh django-cms install and a django settings with the
60-
# CMS_RAW_ID_USERS = CMS_PERMISSION = True
61-
# django throws an OperationalError when running
62-
# ./manage migrate
63-
# because auth_user doesn't exists yet
64-
try:
65-
threshold = threshold and get_user_model().objects.count() > threshold
66-
except OperationalError:
67-
threshold = False
68-
69-
return ['user'] if threshold else []
70-
7136
def get_queryset(self, request):
7237
"""
7338
Queryset change, so user with global change permissions can see
74-
all permissions. Otherwise user can see only permissions for
39+
all permissions. Otherwise, a user can see only permissions for
7540
peoples which are under him (he can't see his permissions, because
7641
this will lead to violation, when he can add more power to himself)
7742
"""
7843
site = Site.objects.get_current(request)
7944

8045
try:
8146
# can see only permissions for users which are under him in tree
82-
qs = self.model.objects.subordinate_to_user(request.user, site)
47+
queryset = self.model.objects.subordinate_to_user(request.user, site)
8348
except NoPermissionsException:
84-
return self.model.objects.none()
85-
return qs.filter(can_view=self.show_with_view_permissions)
49+
queryset = self.model.objects.none()
50+
return queryset
51+
52+
def formfield_for_dbfield(self, db_field, request, **kwargs):
53+
site = Site.objects.get_current(request)
54+
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
55+
if db_field.name == 'user':
56+
formfield._queryset = get_subordinate_users(request.user, site)
57+
if db_field.name == 'group':
58+
formfield._queryset = get_subordinate_groups(request.user, site)
59+
return formfield
60+
61+
62+
class PagePermissionInlineAdmin(PagePermissionAdminMixin, admin.TabularInline):
63+
model = PagePermission
64+
# use special form, so we can override of user and group field
65+
# form = PagePermissionInlineAdminForm
66+
classes = ['collapse', 'collapsed']
67+
fields = ['user', 'group', 'can_add', 'can_change', 'can_delete', 'can_change_advanced_settings',
68+
'can_change_permissions', 'can_move_page', 'grant_on',
69+
]
70+
extra = 0 # edit page load time boost
71+
autocomplete_fields = ['user', 'group']
72+
73+
def get_queryset(self, request):
74+
return super().get_queryset(request).filter(can_view=False)
8675

8776
def get_formset(self, request, obj=None, **kwargs):
8877
"""
@@ -106,26 +95,36 @@ def get_formset(self, request, obj=None, **kwargs):
10695

10796
kwargs['exclude'] = exclude
10897
formset_cls = super().get_formset(request, obj=obj, **kwargs)
109-
qs = self.get_queryset(request)
110-
if obj is not None:
111-
qs = qs.filter(page=obj)
112-
formset_cls._queryset = qs
98+
queryset = self.get_queryset(request)
99+
if obj:
100+
queryset = queryset.filter(page=obj)
101+
formset_cls._queryset = queryset
113102
return formset_cls
114103

115104

116-
class ViewRestrictionInlineAdmin(PagePermissionInlineAdmin):
105+
class ViewRestrictionInlineAdmin(PagePermissionAdminMixin, admin.TabularInline):
106+
model = PagePermission
117107
extra = 0 # edit page load time boost
118-
form = ViewRestrictionInlineAdminForm
119108
verbose_name = _("View restriction")
120109
verbose_name_plural = _("View restrictions")
121-
show_with_view_permissions = True
110+
fields = ['user', 'group', 'grant_on', 'can_view']
111+
autocomplete_fields = ['user', 'group']
112+
113+
def formfield_for_dbfield(self, db_field, request, **kwargs):
114+
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
115+
if db_field.name == 'can_view':
116+
formfield.widget = formfield.hidden_widget()
117+
formfield.initial = True
118+
return formfield
119+
120+
def get_queryset(self, request):
121+
return super().get_queryset(request).filter(can_view=True)
122122

123123

124124
class GlobalPagePermissionAdmin(admin.ModelAdmin):
125125
list_display = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
126126
list_filter = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
127127

128-
form = GlobalPagePermissionAdminForm
129128
search_fields = []
130129
for field in admin_class.search_fields:
131130
search_fields.append("user__%s" % field)
@@ -135,15 +134,13 @@ class GlobalPagePermissionAdmin(admin.ModelAdmin):
135134
list_filter.append('can_change_advanced_settings')
136135

137136
def get_list_filter(self, request):
138-
threshold = get_cms_setting('RAW_ID_USERS')
139-
try:
140-
threshold = threshold and get_user_model().objects.count() > threshold
141-
except OperationalError:
142-
threshold = False
143-
filter_copy = deepcopy(self.list_filter)
144-
if threshold:
145-
filter_copy.remove('user')
146-
return filter_copy
137+
list_filter = list(super().get_list_filter(request))
138+
users_groups_threshold = get_cms_setting('USERS_GROUPS_THRESHOLD')
139+
if Group.objects.count() <= users_groups_threshold:
140+
list_filter.insert(0, 'group')
141+
if get_user_model().objects.count() <= users_groups_threshold:
142+
list_filter.insert(0, 'user')
143+
return list_filter
147144

148145
def has_add_permission(self, request):
149146
site = Site.objects.get_current(request)
@@ -157,23 +154,6 @@ def has_delete_permission(self, request, obj=None):
157154
site = Site.objects.get_current(request)
158155
return permissions.user_can_delete_global_permissions(request.user, site)
159156

160-
@classproperty
161-
def raw_id_fields(cls):
162-
# Dynamically set raw_id_fields based on settings
163-
threshold = get_cms_setting('RAW_ID_USERS')
164-
165-
# Given a fresh django-cms install and a django settings with the
166-
# CMS_RAW_ID_USERS = CMS_PERMISSION = True
167-
# django throws an OperationalError when running
168-
# ./manage migrate
169-
# because auth_user doesn't exists yet
170-
try:
171-
threshold = threshold and get_user_model().objects.count() > threshold
172-
except OperationalError:
173-
threshold = False
174-
175-
return ['user'] if threshold else []
176-
177157

178158
if get_cms_setting('PERMISSION'):
179159
admin.site.register(GlobalPagePermission, GlobalPagePermissionAdmin)

0 commit comments

Comments
 (0)