1# -*- coding: utf-8 -*- 2from copy import deepcopy 3 4from django.contrib import admin 5from django.contrib.admin import site 6from django.contrib.auth import get_user_model 7from django.contrib.auth.admin import UserAdmin 8from django.contrib.sites.models import Site 9from django.db import OperationalError 10from django.utils.translation import gettext_lazy as _ 11 12from cms.admin.forms import GlobalPagePermissionAdminForm, PagePermissionInlineAdminForm, ViewRestrictionInlineAdminForm 13from cms.exceptions import NoPermissionsException 14from cms.models import PagePermission, GlobalPagePermission 15from cms.utils import permissions, page_permissions 16from cms.utils.conf import get_cms_setting 17from cms.utils.helpers import classproperty 18 19 20PERMISSION_ADMIN_INLINES = [] 21 22user_model = get_user_model() 23admin_class = UserAdmin 24for model, admin_instance in site._registry.items(): 25 if model == user_model: 26 admin_class = admin_instance.__class__ 27 28 29class TabularInline(admin.TabularInline): 30 pass 31 32 33class PagePermissionInlineAdmin(TabularInline): 34 model = PagePermission 35 # use special form, so we can override of user and group field 36 form = PagePermissionInlineAdminForm 37 classes = ['collapse', 'collapsed'] 38 extra = 0 # edit page load time boost 39 show_with_view_permissions = False 40 41 def has_change_permission(self, request, obj=None): 42 if not obj: 43 return False 44 return page_permissions.user_can_change_page_permissions( 45 request.user, 46 page=obj, 47 site=obj.node.site, 48 ) 49 50 def has_add_permission(self, request, obj=None): 51 return self.has_change_permission(request, obj) 52 53 @classproperty 54 def raw_id_fields(cls): 55 # Dynamically set raw_id_fields based on settings 56 threshold = get_cms_setting('RAW_ID_USERS') 57 58 # Given a fresh django-cms install and a django settings with the 59 # CMS_RAW_ID_USERS = CMS_PERMISSION = True 60 # django throws an OperationalError when running 61 # ./manage migrate 62 # because auth_user doesn't exists yet 63 try: 64 threshold = threshold and get_user_model().objects.count() > threshold 65 except OperationalError: 66 threshold = False 67 68 return ['user'] if threshold else [] 69 70 def get_queryset(self, request): 71 """ 72 Queryset change, so user with global change permissions can see 73 all permissions. Otherwise user can see only permissions for 74 peoples which are under him (he can't see his permissions, because 75 this will lead to violation, when he can add more power to himself) 76 """ 77 site = Site.objects.get_current(request) 78 79 try: 80 # can see only permissions for users which are under him in tree 81 qs = self.model.objects.subordinate_to_user(request.user, site) 82 except NoPermissionsException: 83 return self.model.objects.none() 84 return qs.filter(can_view=self.show_with_view_permissions) 85 86 def get_formset(self, request, obj=None, **kwargs): 87 """ 88 Some fields may be excluded here. User can change only 89 permissions which are available for him. E.g. if user does not haves 90 can_publish flag, he can't change assign can_publish permissions. 91 """ 92 exclude = self.exclude or [] 93 if obj: 94 user = request.user 95 if not obj.has_add_permission(user): 96 exclude.append('can_add') 97 if not obj.has_delete_permission(user): 98 exclude.append('can_delete') 99 if not obj.has_publish_permission(user): 100 exclude.append('can_publish') 101 if not obj.has_advanced_settings_permission(user): 102 exclude.append('can_change_advanced_settings') 103 if not obj.has_move_page_permission(user): 104 exclude.append('can_move_page') 105 106 kwargs['exclude'] = exclude 107 formset_cls = super(PagePermissionInlineAdmin, self).get_formset(request, obj=obj, **kwargs) 108 qs = self.get_queryset(request) 109 if obj is not None: 110 qs = qs.filter(page=obj) 111 formset_cls._queryset = qs 112 return formset_cls 113 114 115class ViewRestrictionInlineAdmin(PagePermissionInlineAdmin): 116 extra = 0 # edit page load time boost 117 form = ViewRestrictionInlineAdminForm 118 verbose_name = _("View restriction") 119 verbose_name_plural = _("View restrictions") 120 show_with_view_permissions = True 121 122 123class GlobalPagePermissionAdmin(admin.ModelAdmin): 124 list_display = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions'] 125 list_filter = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions'] 126 127 form = GlobalPagePermissionAdminForm 128 search_fields = [] 129 for field in admin_class.search_fields: 130 search_fields.append("user__%s" % field) 131 search_fields.append('group__name') 132 133 list_display.append('can_change_advanced_settings') 134 list_filter.append('can_change_advanced_settings') 135 136 def get_list_filter(self, request): 137 threshold = get_cms_setting('RAW_ID_USERS') 138 try: 139 threshold = threshold and get_user_model().objects.count() > threshold 140 except OperationalError: 141 threshold = False 142 filter_copy = deepcopy(self.list_filter) 143 if threshold: 144 filter_copy.remove('user') 145 return filter_copy 146 147 def has_add_permission(self, request): 148 site = Site.objects.get_current(request) 149 return permissions.user_can_add_global_permissions(request.user, site) 150 151 def has_change_permission(self, request, obj=None): 152 site = Site.objects.get_current(request) 153 return permissions.user_can_change_global_permissions(request.user, site) 154 155 def has_delete_permission(self, request, obj=None): 156 site = Site.objects.get_current(request) 157 return permissions.user_can_delete_global_permissions(request.user, site) 158 159 @classproperty 160 def raw_id_fields(cls): 161 # Dynamically set raw_id_fields based on settings 162 threshold = get_cms_setting('RAW_ID_USERS') 163 164 # Given a fresh django-cms install and a django settings with the 165 # CMS_RAW_ID_USERS = CMS_PERMISSION = True 166 # django throws an OperationalError when running 167 # ./manage migrate 168 # because auth_user doesn't exists yet 169 try: 170 threshold = threshold and get_user_model().objects.count() > threshold 171 except OperationalError: 172 threshold = False 173 174 return ['user'] if threshold else [] 175 176 177if get_cms_setting('PERMISSION'): 178 admin.site.register(GlobalPagePermission, GlobalPagePermissionAdmin) 179 PERMISSION_ADMIN_INLINES.extend([ 180 ViewRestrictionInlineAdmin, 181 PagePermissionInlineAdmin, 182 ]) 183