cms/admin/useradmin.py
from copy import deepcopy
from django.contrib import admin
from django.contrib.admin import site
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.utils.translation import gettext
from cms.admin.forms import PageUserChangeForm, PageUserGroupForm
from cms.exceptions import NoPermissionsException
from cms.models import Page, PagePermission, PageUser, PageUserGroup
from cms.utils.compat.forms import UserAdmin
from cms.utils.conf import get_cms_setting
from cms.utils.permissions import (
get_model_permission_codename,
get_subordinate_groups,
get_subordinate_users,
get_user_permission_level,
)
user_model = get_user_model()
admin_class = UserAdmin
for model, admin_instance in site._registry.items():
if model == user_model:
admin_class = admin_instance.__class__
class GenericCmsPermissionAdmin:
def get_subordinates(self, user, site):
raise NotImplementedError
def _has_change_permissions_permission(self, request):
"""
User is able to add/change objects only if he haves can change
permission on some page.
"""
site = Site.objects.get_current(request)
try:
get_user_permission_level(request.user, site)
except NoPermissionsException:
return False
return True
def get_form(self, request, obj=None, **kwargs):
form_class = super().get_form(request, obj, **kwargs)
form_class._current_user = request.user
return form_class
def get_queryset(self, request):
queryset = super().get_queryset(request)
site = Site.objects.get_current(request)
user_ids = self.get_subordinates(request.user, site).values_list('pk', flat=True)
return queryset.filter(pk__in=user_ids)
def has_add_permission(self, request):
has_model_perm = super().has_add_permission(request)
if not has_model_perm:
return False
return self._has_change_permissions_permission(request)
def has_change_permission(self, request, obj=None):
has_model_perm = super().has_change_permission(request, obj)
if not has_model_perm:
return False
return self._has_change_permissions_permission(request)
def has_delete_permission(self, request, obj=None):
has_model_perm = super().has_delete_permission(request, obj)
if not has_model_perm:
return False
return self._has_change_permissions_permission(request)
def has_view_permission(self, request, obj=None):
# For django 2.1
# Default is to return True if user got `change` perm, but we have to
# get in consideration also cms permission system
return self.has_change_permission(request, obj)
class PageUserAdmin(GenericCmsPermissionAdmin, admin_class):
form = PageUserChangeForm
model = PageUser
def get_subordinates(self, user, site):
return get_subordinate_users(user, site).values_list('pk', flat=True)
def get_readonly_fields(self, request, obj=None):
fields = super().get_readonly_fields(request, obj)
if not request.user.is_superuser:
# Non superusers can't set superuser status on
# their subordinates.
fields = list(fields) + ['is_superuser']
return fields
def save_model(self, request, obj, form, change):
if not change:
# By default set the staff flag to True
# when a PageUser is first created
obj.is_staff = True
# Set the created_by field to the current user
obj.created_by = request.user
super().save_model(request, obj, form, change)
class PageUserGroupAdmin(GenericCmsPermissionAdmin, admin.ModelAdmin):
form = PageUserGroupForm
list_display = ('name', 'created_by')
fieldsets = [
(None, {'fields': ('name',)}),
]
def get_fieldsets(self, request, obj=None):
"""
Nobody can grant more than he haves, so check for user permissions
to Page and User model and render fieldset depending on them.
"""
fieldsets = deepcopy(self.fieldsets)
perm_models = (
(Page, gettext('Page permissions')),
(PageUser, gettext('User & Group permissions')),
(PagePermission, gettext('Page permissions management')),
)
for i, perm_model in enumerate(perm_models):
fields = []
model, title = perm_model
name = model.__name__.lower()
for key in ('add', 'change', 'delete'):
perm_code = get_model_permission_codename(model, action=key)
if request.user.has_perm(perm_code):
fields.append(f'can_{key}_{name}')
if fields:
fieldsets.insert(2 + i, (title, {'fields': (fields,)}))
return fieldsets
def get_subordinates(self, user, site):
return get_subordinate_groups(user, site).values_list('pk', flat=True)
if get_cms_setting('PERMISSION'):
admin.site.register(PageUser, PageUserAdmin)
admin.site.register(PageUserGroup, PageUserGroupAdmin)