Skip to content

Commit

Permalink
add permission option to allow setting pages as HOME
Browse files Browse the repository at this point in the history
# Conflicts:
#	cms/admin/permissionadmin.py
  • Loading branch information
jrief committed Jan 26, 2022
1 parent b7a793c commit f28950e
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 104 deletions.
5 changes: 4 additions & 1 deletion cms/admin/forms.py
@@ -1,3 +1,5 @@
import warnings

from django import forms
from django.apps import apps
from django.contrib.auth import get_permission_codename, get_user_model
Expand Down Expand Up @@ -963,8 +965,9 @@ def run_filters(self, queryset):


class BasePermissionAdminForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
warnings.warn("{} is deprected and will be removed".format(self.__class__),
category=DeprecationWarning, stacklevel=2)
super().__init__(*args, **kwargs)
permission_fields = self._meta.model.get_all_permissions()

Expand Down
10 changes: 9 additions & 1 deletion cms/admin/pageadmin.py
Expand Up @@ -325,6 +325,7 @@ def actions_menu(self, request, object_id, extra_context=None):
'has_change_permissions_permission': self.has_change_permissions_permission(request, obj=page),
'has_move_page_permission': self.has_move_page_permission(request, obj=page),
'has_delete_permission': self.has_delete_permission(request, obj=page),
'can_set_as_home': self.can_set_as_home(request),
'CMS_PERMISSION': get_cms_setting('PERMISSION'),
}

Expand Down Expand Up @@ -684,6 +685,13 @@ def has_delete_permission(self, request, obj=None):
site = self.get_site(request)
return page_permissions.user_can_delete_page(request.user, page=obj, site=site)

def can_set_as_home(self, request):
#if request.user.is_superuser:
# return True
site = self.get_site(request)
perms = permissions.get_global_actions_for_user(request.user, site)
return 'can_set_as_home' in perms

def has_delete_translation_permission(self, request, language, obj=None):
if not obj:
return False
Expand Down Expand Up @@ -1692,7 +1700,7 @@ def pat(regex, fn):
def set_home(self, request, object_id):
page = self.get_object(request, object_id=object_id)

if not self.has_change_permission(request, page):
if not (self.can_set_as_home(request) and self.has_change_permission(request, page)):
raise PermissionDenied("You do not have permission to set 'home'.")

if page is None:
Expand Down
145 changes: 62 additions & 83 deletions cms/admin/permissionadmin.py
@@ -1,22 +1,16 @@
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.auth.admin import UserAdmin
from django.contrib.auth.models import Group
from django.contrib.sites.models import Site
from django.db import OperationalError
from django.utils.translation import gettext_lazy as _

from cms.admin.forms import (
GlobalPagePermissionAdminForm, PagePermissionInlineAdminForm,
ViewRestrictionInlineAdminForm,
)
from cms.exceptions import NoPermissionsException
from cms.models import GlobalPagePermission, PagePermission
from cms.utils import page_permissions, permissions
from cms.utils.conf import get_cms_setting
from cms.utils.helpers import classproperty
from cms.utils.permissions import get_subordinate_users, get_subordinate_groups

PERMISSION_ADMIN_INLINES = []

Expand All @@ -27,18 +21,7 @@
admin_class = admin_instance.__class__


class TabularInline(admin.TabularInline):
pass


class PagePermissionInlineAdmin(TabularInline):
model = PagePermission
# use special form, so we can override of user and group field
form = PagePermissionInlineAdminForm
classes = ['collapse', 'collapsed']
extra = 0 # edit page load time boost
show_with_view_permissions = False

class PagePermissionMixin:
def has_change_permission(self, request, obj=None):
if not obj:
return False
Expand All @@ -51,23 +34,6 @@ def has_change_permission(self, request, obj=None):
def has_add_permission(self, request, obj=None):
return self.has_change_permission(request, obj)

@classproperty
def raw_id_fields(cls):
# Dynamically set raw_id_fields based on settings
threshold = get_cms_setting('RAW_ID_USERS')

# Given a fresh django-cms install and a django settings with the
# CMS_RAW_ID_USERS = CMS_PERMISSION = True
# django throws an OperationalError when running
# ./manage migrate
# because auth_user doesn't exists yet
try:
threshold = threshold and get_user_model().objects.count() > threshold
except OperationalError:
threshold = False

return ['user'] if threshold else []

def get_queryset(self, request):
"""
Queryset change, so user with global change permissions can see
Expand All @@ -76,13 +42,36 @@ def get_queryset(self, request):
this will lead to violation, when he can add more power to himself)
"""
site = Site.objects.get_current(request)

try:
# can see only permissions for users which are under him in tree
qs = self.model.objects.subordinate_to_user(request.user, site)
queryset = self.model.objects.subordinate_to_user(request.user, site)
except NoPermissionsException:
return self.model.objects.none()
return qs.filter(can_view=self.show_with_view_permissions)
return queryset

def formfield_for_dbfield(self, db_field, request, **kwargs):
site = Site.objects.get_current(request)
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name == 'user':
formfield._queryset = get_subordinate_users(request.user, site)
if db_field.name == 'group':
formfield._queryset = get_subordinate_groups(request.user, site)
return formfield


class PagePermissionInlineAdmin(PagePermissionMixin, admin.TabularInline):
model = PagePermission
# use special form, so we can override of user and group field
# form = PagePermissionInlineAdminForm
classes = ['collapse', 'collapsed']
fields = ['user', 'group', 'can_add', 'can_change', 'can_delete', 'can_publish', 'can_change_advanced_settings',
'can_change_permissions', 'can_move_page', 'grant_on',
]
extra = 0 # edit page load time boost
autocomplete_fields = ['user', 'group']

def get_queryset(self, request):
return super().get_queryset(request).filter(can_view=False)

def get_formset(self, request, obj=None, **kwargs):
"""
Expand All @@ -106,44 +95,51 @@ def get_formset(self, request, obj=None, **kwargs):

kwargs['exclude'] = exclude
formset_cls = super().get_formset(request, obj=obj, **kwargs)
qs = self.get_queryset(request)
if obj is not None:
qs = qs.filter(page=obj)
formset_cls._queryset = qs
queryset = self.get_queryset(request)
if obj:
queryset = queryset.filter(page=obj)
formset_cls._queryset = queryset
return formset_cls


class ViewRestrictionInlineAdmin(PagePermissionInlineAdmin):
class ViewRestrictionInlineAdmin(PagePermissionMixin, admin.TabularInline):
model = PagePermission
extra = 0 # edit page load time boost
form = ViewRestrictionInlineAdminForm
verbose_name = _("View restriction")
verbose_name_plural = _("View restrictions")
show_with_view_permissions = True
fields = ['user', 'group', 'grant_on', 'can_view']
autocomplete_fields = ['user', 'group']

def formfield_for_dbfield(self, db_field, request, **kwargs):
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name == 'can_view':
formfield.widget = formfield.hidden_widget()
formfield.initial = True
return formfield

class GlobalPagePermissionAdmin(admin.ModelAdmin):
list_display = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
list_filter = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions']
def get_queryset(self, request):
return super().get_queryset(request).filter(can_view=True)

form = GlobalPagePermissionAdminForm
search_fields = []
for field in admin_class.search_fields:
search_fields.append("user__%s" % field)
search_fields.append('group__name')

list_display.append('can_change_advanced_settings')
list_filter.append('can_change_advanced_settings')
class GlobalPagePermissionAdmin(admin.ModelAdmin):
list_display = ['user', 'group', 'can_change', 'can_delete', 'can_publish', 'can_change_permissions',
'can_change_advanced_settings']
list_filter = ['can_change', 'can_delete', 'can_publish', 'can_change_permissions',
'can_change_advanced_settings']
fields = ['user', 'group', 'can_add', 'can_change', 'can_delete', 'can_publish', 'can_change_advanced_settings',
'can_change_permissions', 'can_move_page', 'can_view', 'can_set_as_home', 'sites']
search_fields = ['user__{}'.format(field) for field in admin_class.search_fields] + ['group__name']
autocomplete_fields = ['user', 'group']
filter_horizontal = ['sites']
list_filter_threshold = 100 # if the number of users and/or groups exceeds this threshold, don't add a filter

def get_list_filter(self, request):
threshold = get_cms_setting('RAW_ID_USERS')
try:
threshold = threshold and get_user_model().objects.count() > threshold
except OperationalError:
threshold = False
filter_copy = deepcopy(self.list_filter)
if threshold:
filter_copy.remove('user')
return filter_copy
list_filter = list(super().get_list_filter(request))
if Group.objects.count() < self.list_filter_threshold:
list_filter.insert(0, 'group')
if get_user_model().objects.count() < self.list_filter_threshold:
list_filter.insert(0, 'user')
return list_filter

def has_add_permission(self, request):
site = Site.objects.get_current(request)
Expand All @@ -157,23 +153,6 @@ def has_delete_permission(self, request, obj=None):
site = Site.objects.get_current(request)
return permissions.user_can_delete_global_permissions(request.user, site)

@classproperty
def raw_id_fields(cls):
# Dynamically set raw_id_fields based on settings
threshold = get_cms_setting('RAW_ID_USERS')

# Given a fresh django-cms install and a django settings with the
# CMS_RAW_ID_USERS = CMS_PERMISSION = True
# django throws an OperationalError when running
# ./manage migrate
# because auth_user doesn't exists yet
try:
threshold = threshold and get_user_model().objects.count() > threshold
except OperationalError:
threshold = False

return ['user'] if threshold else []


if get_cms_setting('PERMISSION'):
admin.site.register(GlobalPagePermission, GlobalPagePermissionAdmin)
Expand Down
18 changes: 13 additions & 5 deletions cms/api.py
Expand Up @@ -333,7 +333,7 @@ def add_plugin(placeholder, plugin_type, language, position='last-child',
def create_page_user(created_by, user,
can_add_page=True, can_view_page=True,
can_change_page=True, can_delete_page=True,
can_recover_page=True, can_add_pageuser=True,
can_recover_page=True, can_set_as_home=False, can_add_pageuser=True,
can_change_pageuser=True, can_delete_pageuser=True,
can_add_pagepermission=True,
can_change_pagepermission=True,
Expand All @@ -346,8 +346,14 @@ def create_page_user(created_by, user,
from cms.admin.forms import save_permissions
if grant_all:
# just be lazy
return create_page_user(created_by, user, True, True, True, True,
True, True, True, True, True, True, True)
return create_page_user(created_by, user,
can_add_page=True, can_view_page=True,
can_change_page=True, can_delete_page=True,
can_recover_page=True, can_set_as_home=True, can_add_pageuser=True,
can_change_pageuser=True, can_delete_pageuser=True,
can_add_pagepermission=True,
can_change_pagepermission=True,
can_delete_pagepermission=True)

# validate created_by
assert isinstance(created_by, get_user_model())
Expand All @@ -358,6 +364,7 @@ def create_page_user(created_by, user,
'can_change_page': can_change_page,
'can_delete_page': can_delete_page,
'can_recover_page': can_recover_page,
'can_set_as_home': can_set_as_home,
'can_add_pageuser': can_add_pageuser,
'can_change_pageuser': can_change_pageuser,
'can_delete_pageuser': can_delete_pageuser,
Expand All @@ -380,7 +387,7 @@ def assign_user_to_page(page, user, grant_on=ACCESS_PAGE_AND_DESCENDANTS,
can_add=False, can_change=False, can_delete=False,
can_change_advanced_settings=False, can_publish=False,
can_change_permissions=False, can_move_page=False,
can_recover_page=True, can_view=False,
can_recover_page=True, can_set_as_home=False, can_view=False,
grant_all=False, global_permission=False):
"""
Assigns given user to page, and gives him requested permissions.
Expand All @@ -404,7 +411,8 @@ def assign_user_to_page(page, user, grant_on=ACCESS_PAGE_AND_DESCENDANTS,
page_permission.save()
if global_permission:
page_permission = GlobalPagePermission(
user=user, can_recover_page=can_recover_page, **data)
user=user, can_recover_page=can_recover_page, can_set_as_home=can_set_as_home,
**data)
page_permission.save()
page_permission.sites.add(get_current_site())
return page_permission
Expand Down
18 changes: 18 additions & 0 deletions cms/migrations/0023_globalpagepermission_can_set_as_home.py
@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2022-01-25 11:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('cms', '0022_auto_20180620_1551'),
]

operations = [
migrations.AddField(
model_name='globalpagepermission',
name='can_set_as_home',
field=models.BooleanField(default=False, help_text='Can set first tier pages as home page', verbose_name='Can set as home'),
),
]

0 comments on commit f28950e

Please sign in to comment.