PageRenderTime 69ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

/cms/admin/permissionadmin.py

https://github.com/keimlink/django-cms
Python | 228 lines | 158 code | 20 blank | 50 comment | 23 complexity | 0a0187de9340453167a4894de81f4cce MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. from copy import deepcopy
  3. from django.contrib import admin
  4. from django.contrib.admin import site
  5. from django.contrib.auth import get_user_model, get_permission_codename
  6. from django.contrib.auth.admin import UserAdmin
  7. from django.db import OperationalError
  8. from django.utils.translation import ugettext, ugettext_lazy as _
  9. from cms.admin.forms import GlobalPagePermissionAdminForm, PagePermissionInlineAdminForm, ViewRestrictionInlineAdminForm
  10. from cms.exceptions import NoPermissionsException
  11. from cms.models import Page, PagePermission, GlobalPagePermission, PageUser
  12. from cms.utils.conf import get_cms_setting
  13. from cms.utils.helpers import classproperty
  14. from cms.utils.permissions import get_user_permission_level
  15. PERMISSION_ADMIN_INLINES = []
  16. user_model = get_user_model()
  17. admin_class = UserAdmin
  18. for model, admin_instance in site._registry.items():
  19. if model == user_model:
  20. admin_class = admin_instance.__class__
  21. class TabularInline(admin.TabularInline):
  22. pass
  23. class PagePermissionInlineAdmin(TabularInline):
  24. model = PagePermission
  25. # use special form, so we can override of user and group field
  26. form = PagePermissionInlineAdminForm
  27. classes = ['collapse', 'collapsed']
  28. exclude = ['can_view']
  29. extra = 0 # edit page load time boost
  30. @classproperty
  31. def raw_id_fields(cls):
  32. # Dynamically set raw_id_fields based on settings
  33. threshold = get_cms_setting('RAW_ID_USERS')
  34. # Given a fresh django-cms install and a django settings with the
  35. # CMS_RAW_ID_USERS = CMS_PERMISSION = True
  36. # django throws an OperationalError when running
  37. # ./manage migrate
  38. # because auth_user doesn't exists yet
  39. try:
  40. threshold = threshold and get_user_model().objects.count() > threshold
  41. except OperationalError:
  42. threshold = False
  43. return ['user'] if threshold else []
  44. def get_queryset(self, request):
  45. """
  46. Queryset change, so user with global change permissions can see
  47. all permissions. Otherwise can user see only permissions for
  48. peoples which are under him (he can't see his permissions, because
  49. this will lead to violation, when he can add more power to itself)
  50. """
  51. # can see only permissions for users which are under him in tree
  52. # here an exception can be thrown
  53. try:
  54. qs = self.model.objects.subordinate_to_user(request.user)
  55. return qs.filter(can_view=False)
  56. except NoPermissionsException:
  57. return self.objects.get_empty_query_set()
  58. def get_formset(self, request, obj=None, **kwargs):
  59. """
  60. Some fields may be excluded here. User can change only
  61. permissions which are available for him. E.g. if user does not haves
  62. can_publish flag, he can't change assign can_publish permissions.
  63. """
  64. exclude = self.exclude or []
  65. if obj:
  66. if not obj.has_add_permission(request):
  67. exclude.append('can_add')
  68. if not obj.has_delete_permission(request):
  69. exclude.append('can_delete')
  70. if not obj.has_publish_permission(request):
  71. exclude.append('can_publish')
  72. if not obj.has_advanced_settings_permission(request):
  73. exclude.append('can_change_advanced_settings')
  74. if not obj.has_move_page_permission(request):
  75. exclude.append('can_move_page')
  76. formset_cls = super(PagePermissionInlineAdmin, self
  77. ).get_formset(request, obj=None, exclude=exclude, **kwargs)
  78. qs = self.get_queryset(request)
  79. if obj is not None:
  80. qs = qs.filter(page=obj)
  81. formset_cls._queryset = qs
  82. return formset_cls
  83. class ViewRestrictionInlineAdmin(PagePermissionInlineAdmin):
  84. extra = 0 # edit page load time boost
  85. form = ViewRestrictionInlineAdminForm
  86. verbose_name = _("View restriction")
  87. verbose_name_plural = _("View restrictions")
  88. exclude = [
  89. 'can_add', 'can_change', 'can_delete', 'can_view',
  90. 'can_publish', 'can_change_advanced_settings', 'can_move_page',
  91. 'can_change_permissions'
  92. ]
  93. def get_formset(self, request, obj=None, **kwargs):
  94. """
  95. Some fields may be excluded here. User can change only permissions
  96. which are available for him. E.g. if user does not haves can_publish
  97. flag, he can't change assign can_publish permissions.
  98. """
  99. formset_cls = super(PagePermissionInlineAdmin, self).get_formset(request, obj, **kwargs)
  100. qs = self.get_queryset(request)
  101. if obj is not None:
  102. qs = qs.filter(page=obj)
  103. formset_cls._queryset = qs
  104. return formset_cls
  105. def get_queryset(self, request):
  106. """
  107. Returns a QuerySet of all model instances that can be edited by the
  108. admin site. This is used by changelist_view.
  109. """
  110. qs = self.model.objects.subordinate_to_user(request.user)
  111. return qs.filter(can_view=True)
  112. class GlobalPagePermissionAdmin(admin.ModelAdmin):
  113. list_display = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
  114. list_filter = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
  115. form = GlobalPagePermissionAdminForm
  116. search_fields = []
  117. for field in admin_class.search_fields:
  118. search_fields.append("user__%s" % field)
  119. search_fields.append('group__name')
  120. exclude = []
  121. list_display.append('can_change_advanced_settings')
  122. list_filter.append('can_change_advanced_settings')
  123. def get_list_filter(self, request):
  124. threshold = get_cms_setting('RAW_ID_USERS')
  125. try:
  126. threshold = threshold and get_user_model().objects.count() > threshold
  127. except OperationalError:
  128. threshold = False
  129. filter_copy = deepcopy(self.list_filter)
  130. if threshold:
  131. filter_copy.remove('user')
  132. return filter_copy
  133. @classproperty
  134. def raw_id_fields(cls):
  135. # Dynamically set raw_id_fields based on settings
  136. threshold = get_cms_setting('RAW_ID_USERS')
  137. # Given a fresh django-cms install and a django settings with the
  138. # CMS_RAW_ID_USERS = CMS_PERMISSION = True
  139. # django throws an OperationalError when running
  140. # ./manage migrate
  141. # because auth_user doesn't exists yet
  142. try:
  143. threshold = threshold and get_user_model().objects.count() > threshold
  144. except OperationalError:
  145. threshold = False
  146. return ['user'] if threshold else []
  147. class GenericCmsPermissionAdmin(object):
  148. """
  149. Custom mixin for permission-enabled admin interfaces.
  150. """
  151. def update_permission_fieldsets(self, request, obj=None):
  152. """
  153. Nobody can grant more than he haves, so check for user permissions
  154. to Page and User model and render fieldset depending on them.
  155. """
  156. fieldsets = deepcopy(self.fieldsets)
  157. perm_models = (
  158. (Page, ugettext('Page permissions')),
  159. (PageUser, ugettext('User & Group permissions')),
  160. (PagePermission, ugettext('Page permissions management')),
  161. )
  162. for i, perm_model in enumerate(perm_models):
  163. model, title = perm_model
  164. opts, fields = model._meta, []
  165. name = model.__name__.lower()
  166. for key in ('add', 'change', 'delete'):
  167. perm_code = '%s.%s' % (opts.app_label, get_permission_codename(key, opts))
  168. if request.user.has_perm(perm_code):
  169. fields.append('can_%s_%s' % (key, name))
  170. if fields:
  171. fieldsets.insert(2 + i, (title, {'fields': (fields,)}))
  172. return fieldsets
  173. def _has_change_permissions_permission(self, request):
  174. """
  175. User is able to add/change objects only if he haves can change
  176. permission on some page.
  177. """
  178. try:
  179. get_user_permission_level(request.user)
  180. except NoPermissionsException:
  181. return False
  182. return True
  183. def has_add_permission(self, request):
  184. return self._has_change_permissions_permission(request) and \
  185. super(self.__class__, self).has_add_permission(request)
  186. def has_change_permission(self, request, obj=None):
  187. return self._has_change_permissions_permission(request) and \
  188. super(self.__class__, self).has_change_permission(request, obj)
  189. if get_cms_setting('PERMISSION'):
  190. admin.site.register(GlobalPagePermission, GlobalPagePermissionAdmin)
  191. PERMISSION_ADMIN_INLINES.extend([
  192. ViewRestrictionInlineAdmin,
  193. PagePermissionInlineAdmin,
  194. ])