Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Re-introduce page-level publish permission just as in v4.0 #7837

Merged
merged 15 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cms/admin/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,7 @@ class Meta:
"can_add",
"can_change",
"can_delete",
"can_publish",
"can_change_advanced_settings",
"can_change_permissions",
"can_move_page",
Expand Down Expand Up @@ -1204,6 +1205,7 @@ class Meta:
"can_add",
"can_change",
"can_delete",
"can_publish",
"can_change_advanced_settings",
"can_change_permissions",
"can_move_page",
Expand Down
6 changes: 4 additions & 2 deletions cms/admin/permissionadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def get_formset(self, request, obj=None, **kwargs):
exclude.append('can_add')
if not obj.has_delete_permission(user):
exclude.append('can_delete')
if not obj.has_publish_permission(user):
exclude.append('can_publish')
if not obj.has_advanced_settings_permission(user):
exclude.append('can_change_advanced_settings')
if not obj.has_move_page_permission(user):
Expand All @@ -120,8 +122,8 @@ class ViewRestrictionInlineAdmin(PagePermissionInlineAdmin):


class GlobalPagePermissionAdmin(admin.ModelAdmin):
list_display = ['user', 'group', 'can_change', 'can_delete', 'can_change_permissions']
list_filter = ['user', 'group', 'can_change', 'can_delete', 'can_change_permissions']
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']

form = GlobalPagePermissionAdminForm
search_fields = []
Expand Down
8 changes: 3 additions & 5 deletions cms/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,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_publish_page=True, can_add_pageuser=True,
can_change_pageuser=True, can_delete_pageuser=True,
can_add_pagepermission=True,
can_change_pagepermission=True,
Expand Down Expand Up @@ -466,7 +466,7 @@ def create_page_user(created_by, user,
'can_view_page': can_view_page,
'can_change_page': can_change_page,
'can_delete_page': can_delete_page,
'can_recover_page': can_recover_page,
'can_publish_page': can_publish_page,
'can_add_pageuser': can_add_pageuser,
'can_change_pageuser': can_change_pageuser,
'can_delete_pageuser': can_delete_pageuser,
Expand Down Expand Up @@ -506,15 +506,13 @@ def assign_user_to_page(page, user, grant_on=ACCESS_PAGE_AND_DESCENDANTS,
:param can_*: Permissions to grant
:param bool grant_all: Grant all permissions to the user
"""
if can_publish is not None:
warnings.warn('This API function no longer accepts a "can_publish" argument.',
UserWarning, stacklevel=2)

grant_all = grant_all and not global_permission
data = {
'can_add': can_add or grant_all,
'can_change': can_change or grant_all,
'can_delete': can_delete or grant_all,
'can_publish': can_publish or grant_all,
'can_change_advanced_settings': can_change_advanced_settings or grant_all,
'can_change_permissions': can_change_permissions or grant_all,
'can_move_page': can_move_page or grant_all,
Expand Down
2 changes: 1 addition & 1 deletion cms/cache/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
PERMISSION_KEYS = [
'add_page', 'change_page', 'change_page_advanced_settings',
'change_page_permissions', 'delete_page', 'move_page',
'view_page',
'publish_page', 'view_page',
]


Expand Down
3 changes: 2 additions & 1 deletion cms/cache/placeholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ def _get_placeholder_cache_key(placeholder, lang, site_id, request, soft=False):
"""
prefix = get_cms_setting('CACHE_PREFIX')
version, vary_on_list = _get_placeholder_cache_version(placeholder, lang, site_id)
main_key = f'{prefix}|render_placeholder|id:{placeholder.pk}|lang:{lang}|site:{site_id}|tz:{get_timezone_name()}|v:{version}'
tz = get_timezone_name()
main_key = f"{prefix}|render_placeholder|id:{placeholder.pk}|lang:{lang}|site:{site_id}|tz:{tz}|v:{version}"

if not soft:
# We are about to write to the cache, so we want to get the latest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.23 on 2024-03-11 09:32

from django.db import migrations, models


class Migration(migrations.Migration):

replaces = [('cms', '0035_auto_20230822_2208'), ('cms', '0036_auto_20240311_1028')]

dependencies = [
('cms', '0034_remove_pagecontent_placeholders'),
]

operations = [
migrations.AlterModelOptions(
name='pagecontent',
options={'default_permissions': [], 'verbose_name': 'page content', 'verbose_name_plural': 'page contents'},
),
migrations.AlterModelOptions(
name='page',
options={'default_permissions': ('add', 'change', 'delete'), 'permissions': (('view_page', 'Can view page'), ('publish_page', 'Can publish page'), ('edit_static_placeholder', 'Can edit static placeholders')), 'verbose_name': 'page', 'verbose_name_plural': 'pages'},
),
]
27 changes: 27 additions & 0 deletions cms/migrations/0036_auto_20240311_1028.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.2.23 on 2024-03-11 10:28

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('cms', '0035_auto_20230822_2208'),
]

operations = [
migrations.AlterModelOptions(
name='page',
options={'default_permissions': ('add', 'change', 'delete'), 'permissions': (('view_page', 'Can view page'), ('publish_page', 'Can publish page'), ('edit_static_placeholder', 'Can edit static placeholders')), 'verbose_name': 'page', 'verbose_name_plural': 'pages'},
),
migrations.AddField(
model_name='globalpagepermission',
name='can_publish',
field=models.BooleanField(default=True, verbose_name='can publish'),
),
migrations.AddField(
model_name='pagepermission',
name='can_publish',
field=models.BooleanField(default=True, verbose_name='can publish'),
),
]
3 changes: 3 additions & 0 deletions cms/models/contentmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ def toggle_in_navigation(self, set_to=None):
def has_placeholder_change_permission(self, user):
return self.page.has_change_permission(user)

def has_publish_permission(self, user):
return self.page.has_publish_permission(user)

def rescan_placeholders(self):
"""
Rescan and if necessary create placeholders in the current template.
Expand Down
5 changes: 5 additions & 0 deletions cms/models/pagemodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class Meta:
default_permissions = ('add', 'change', 'delete')
permissions = (
('view_page', 'Can view page'),
('publish_page', 'Can publish page'),
('edit_static_placeholder', 'Can edit static placeholders'),
)
verbose_name = _('page')
Expand Down Expand Up @@ -995,6 +996,10 @@ def has_delete_translation_permission(self, user, language):
from cms.utils.page_permissions import user_can_delete_page_translation
return user_can_delete_page_translation(user, page=self, language=language)

def has_publish_permission(self, user):
from cms.utils.page_permissions import user_can_publish_page
return user_can_publish_page(user, page=self)

def has_advanced_settings_permission(self, user):
from cms.utils.page_permissions import (
user_can_change_page_advanced_settings,
Expand Down
8 changes: 8 additions & 0 deletions cms/models/permissionmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class AbstractPagePermission(models.Model):
can_change = models.BooleanField(_("can edit"), default=True)
can_add = models.BooleanField(_("can add"), default=True)
can_delete = models.BooleanField(_("can delete"), default=True)
can_publish = models.BooleanField(_("can publish"), default=True)
can_change_advanced_settings = models.BooleanField(_("can change advanced settings"), default=False)
can_change_permissions = models.BooleanField(
_("can change permissions"), default=False, help_text=_("on page level")
Expand Down Expand Up @@ -113,6 +114,11 @@ def clean(self):
"to change the page. Edit permissions required.")
raise ValidationError(message)

if self.can_publish:
message = _("Users can't publish a page without permissions "
"to change the page. Edit permissions required.")
raise ValidationError(message)

if self.can_change_advanced_settings:
message = _("Users can't change page advanced settings without permissions "
"to change the page. Edit permissions required.")
Expand Down Expand Up @@ -156,6 +162,7 @@ def get_all_permissions(cls):
'can_add',
'can_change',
'can_delete',
'can_publish',
'can_change_advanced_settings',
'can_change_permissions',
'can_move_page',
Expand All @@ -174,6 +181,7 @@ def get_permissions_by_action(cls):
'change_page_permissions': ['can_change', 'can_change_permissions'],
'delete_page': ['can_change', 'can_delete'],
'delete_page_translation': ['can_change', 'can_delete'],
'publish_page': ['can_change', 'can_publish'],
'move_page': ['can_change', 'can_move_page'],
'view_page': ['can_view'],
}
Expand Down
1 change: 1 addition & 0 deletions cms/templates/admin/cms/page/permissions.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<td class="can_change">{{ permission.can_change|boolean_icon }}</td>
<td class="can_add">{{ permission.can_add|boolean_icon }}</td>
<td class="can_delete">{{ permission.can_delete|boolean_icon }}</td>
<td class="can_publish">{{ permission.can_publish|boolean_icon }}</td>
<td class="can_change_permissions">{{ permission.can_change_permissions|boolean_icon }}</td>
<td class="can_move_page">{{ permission.can_move_page|boolean_icon }}</td>
<td class="can_view">{{ permission.can_view|boolean_icon }}</td>
Expand Down
3 changes: 3 additions & 0 deletions cms/test_utils/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def add_global_permission(self, user, **kwargs):
'can_add': False,
'can_change': False,
'can_delete': False,
'can_publish': False,
'can_change_advanced_settings': False,
'can_change_permissions': False,
'can_move_page': False,
Expand All @@ -140,6 +141,7 @@ def add_page_permission(self, user, page, **kwargs):
'can_add': False,
'can_change': False,
'can_delete': False,
'can_publish': False,
'can_change_advanced_settings': False,
'can_change_permissions': False,
'can_move_page': False,
Expand Down Expand Up @@ -209,6 +211,7 @@ def _add_default_permissions(self, user):
user.user_permissions.add(Permission.objects.get(codename='delete_link'))
user.user_permissions.add(Permission.objects.get(codename='change_link'))
# Page permissions
user.user_permissions.add(Permission.objects.get(codename='publish_page'))
user.user_permissions.add(Permission.objects.get(codename='add_page'))
user.user_permissions.add(Permission.objects.get(codename='change_page'))
user.user_permissions.add(Permission.objects.get(codename='delete_page'))
Expand Down
2 changes: 2 additions & 0 deletions cms/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def _get_staff_user(self, use_global_permissions=True):
user=normal_guy,
can_change=True,
can_delete=True,
can_publish=True,
can_change_advanced_settings=False,
can_change_permissions=False,
can_move_page=True,
Expand Down Expand Up @@ -516,6 +517,7 @@ def _give_cms_permissions(self, user, save=True):
user=user,
can_change=True,
can_delete=True,
can_publish=True,
can_change_advanced_settings=False,
can_change_permissions=False,
can_move_page=True,
Expand Down
9 changes: 5 additions & 4 deletions cms/tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from cms.test_utils.testcases import CMSTestCase
from cms.utils.page_permissions import (
get_change_id_list,
user_can_change_page,
user_can_publish_page,
)


Expand Down Expand Up @@ -76,14 +76,15 @@ def test_cached_permission_precedence(self):
)
page_permission = GlobalPagePermission.objects.create(
can_change=True,
can_publish=True,
user=self.user_normal,
)
page_permission.sites.add(Site.objects.get_current())
set_permission_cache(self.user_normal, "change_page", [])
set_permission_cache(self.user_normal, "publish_page", [])

can_change = user_can_change_page(
can_publish = user_can_publish_page(
self.user_normal,
page,
Site.objects.get_current(),
)
self.assertTrue(can_change)
self.assertTrue(can_publish)
24 changes: 15 additions & 9 deletions cms/tests/test_permmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@ class PermissionModeratorTests(CMSTestCase):

def setUp(self):
# create super user
self.user_super = self._create_user("super", is_staff=True,
is_superuser=True)
self.user_staff = self._create_user("staff", is_staff=True,
add_default_permissions=True)
self.user_master = self._create_user("master", is_staff=True,
add_default_permissions=True)
self.user_slave = self._create_user("slave", is_staff=True,
add_default_permissions=True)
self.user_super = self._create_user("super", is_staff=True, is_superuser=True)

self.user_staff = self._create_user("staff", is_staff=True, add_default_permissions=True)
self.add_permission(self.user_staff, 'publish_page')

self.user_master = self._create_user("master", is_staff=True, add_default_permissions=True)
self.add_permission(self.user_master, 'publish_page')

self.user_slave = self._create_user("slave", is_staff=True, add_default_permissions=True)

self.user_normal = self._create_user("normal", is_staff=False)
self.user_normal.user_permissions.add(Permission.objects.get(codename='publish_page'))

with self.login_user_context(self.user_super):
self.home_page = create_page("home", "nav_playground.html", "en",
Expand Down Expand Up @@ -105,7 +108,7 @@ def setUp(self):
page_a = create_page("pageA", "nav_playground.html", "en",
created_by=self.user_super)
assign_user_to_page(page_a, self.user_master,
can_add=True, can_change=True, can_delete=True,
can_add=True, can_change=True, can_delete=True, can_publish=True,
can_move_page=True)

def _add_plugin(self, user, page):
Expand Down Expand Up @@ -214,6 +217,9 @@ def test_user_globalpermission(self):
user_global.is_staff = False
user_global.save() # Prevent is_staff permission
global_page = create_page("global", "nav_playground.html", "en")
# Removed call since global page user doesn't have publish permission
# global_page = publish_page(global_page, user_global)
# it's allowed for the normal user to view the page
assign_user_to_page(global_page, user_global, global_permission=True, can_view=True)

url = global_page.get_absolute_url('en')
Expand Down
5 changes: 3 additions & 2 deletions cms/utils/apphook_reload.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ def reload_urlconf(urlconf=None, new_revision=None):


def log_reloading_apphook(global_revision, local_revision):
debug_msg = f" New revision!!!! RELOAD!\n {global_revision} ({type(global_revision)})\n -> {local_revision} ({type(local_revision)})"
logger.debug(debug_msg)
logger.debug(f" New revision!!!! RELOAD!\n"
f" {global_revision} ({type(global_revision)})\n"
f" -> {local_revision} ({type(local_revision)})")


def debug_check_url(url_name):
Expand Down
Loading