From 758da5b98762681c0d9d8e7c9b8d94085cd77e0f Mon Sep 17 00:00:00 2001 From: Paulo Date: Mon, 11 Jan 2016 16:39:51 -0500 Subject: [PATCH 1/4] fixes issue with page menu missing --- cms/cms_toolbar.py | 17 ++++++++++++++--- cms/models/pagemodel.py | 12 ++++++++---- cms/utils/permissions.py | 22 +++++++++++++++++++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/cms/cms_toolbar.py b/cms/cms_toolbar.py index 00f9ce02a13..f516b33f0bb 100644 --- a/cms/cms_toolbar.py +++ b/cms/cms_toolbar.py @@ -19,7 +19,10 @@ from cms.utils.i18n import get_language_tuple, force_language, get_language_dict from cms.utils.compat.dj import is_installed from cms.utils import get_cms_setting -from cms.utils.permissions import get_user_sites_queryset +from cms.utils.permissions import ( + get_user_sites_queryset, + has_auth_page_permission, +) from cms.utils.urlutils import add_url_parameters, admin_reverse from menus.utils import DefaultLanguageChanger @@ -252,8 +255,16 @@ def has_publish_permission(self): def has_page_change_permission(self): if not hasattr(self, 'page_change_permission'): - self.page_change_permission = can_change_page(self.request) - + if not self.page and not get_cms_setting('PERMISSION'): + # We can't check permissions for an individual page + # and can't check global cms permissions because + # user opted out of them. + # So just check django auth permissions. + user = self.request.user + can_change = has_auth_page_permission(user, action='change') + else: + can_change = can_change_page(self.request) + self.page_change_permission = can_change return self.page_change_permission def page_is_pending(self, page, language): diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py index 5a6e8b8939f..acaae6f9b09 100644 --- a/cms/models/pagemodel.py +++ b/cms/models/pagemodel.py @@ -1048,21 +1048,25 @@ def has_view_permission(self, request, user=None): return request.user.has_perm(codename) def has_change_permission(self, request, user=None): - opts = self._meta + from cms.utils.permissions import has_auth_page_permission + if not user: user = request.user + if user.is_superuser: return True - return (user.has_perm(opts.app_label + '.' + get_permission_codename('change', opts)) + return (has_auth_page_permission(user, action='change') and self.has_generic_permission(request, "change")) def has_delete_permission(self, request, user=None): - opts = self._meta + from cms.utils.permissions import has_auth_page_permission + if not user: user = request.user + if user.is_superuser: return True - return (user.has_perm(opts.app_label + '.' + get_permission_codename('delete', opts)) + return (has_auth_page_permission(user, action='delete') and self.has_generic_permission(request, "delete")) def has_publish_permission(self, request, user=None): diff --git a/cms/utils/permissions.py b/cms/utils/permissions.py index 233d163af84..1933b4f2d66 100644 --- a/cms/utils/permissions.py +++ b/cms/utils/permissions.py @@ -104,6 +104,22 @@ def has_any_page_change_permissions(request): ).exists() +def get_model_permission_codename(model, action): + opts = model._meta + return opts.app_label + '.' + get_permission_codename(action, opts) + + +def has_auth_page_permission(user, action): + """ + Returns True if the user is a superuser or has + the cms.page {action} permission set via django's permission model. + """ + if not user.is_superuser: + permission = get_model_permission_codename(Page, action=action) + return user.has_perm(permission) + return True + + def has_page_change_permission(request): """ Return true if the current user has permission to change this page. @@ -113,12 +129,12 @@ def has_page_change_permission(request): """ from cms.utils.helpers import current_site - opts = Page._meta + user = request.user site = current_site(request) global_change_perm = GlobalPagePermission.objects.user_has_change_permission( request.user, site).exists() - return request.user.is_superuser or ( - request.user.has_perm(opts.app_label + '.' + get_permission_codename('change', opts)) + return user.is_superuser or ( + has_auth_page_permission(user, action='change') and global_change_perm or has_any_page_change_permissions(request)) From 55ce5c0dd21d97b8124ae753065edd8495dc8ee6 Mon Sep 17 00:00:00 2001 From: Paulo Date: Mon, 11 Jan 2016 16:41:49 -0500 Subject: [PATCH 2/4] cosmetics --- cms/utils/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/utils/permissions.py b/cms/utils/permissions.py index 1933b4f2d66..e8a366e0b28 100644 --- a/cms/utils/permissions.py +++ b/cms/utils/permissions.py @@ -132,7 +132,7 @@ def has_page_change_permission(request): user = request.user site = current_site(request) global_change_perm = GlobalPagePermission.objects.user_has_change_permission( - request.user, site).exists() + user, site).exists() return user.is_superuser or ( has_auth_page_permission(user, action='change') and global_change_perm or has_any_page_change_permissions(request)) From d99f1cfc3e114db611ab85fe8062a4e8bb09ae2e Mon Sep 17 00:00:00 2001 From: Paulo Date: Tue, 12 Jan 2016 13:16:44 -0500 Subject: [PATCH 3/4] fixes failing tests --- cms/cms_toolbar.py | 5 ++++- cms/models/pagemodel.py | 1 - cms/tests/toolbar.py | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cms/cms_toolbar.py b/cms/cms_toolbar.py index f516b33f0bb..d98e453b1ab 100644 --- a/cms/cms_toolbar.py +++ b/cms/cms_toolbar.py @@ -219,6 +219,7 @@ def render_addons(self, context): @toolbar_pool.register class PageToolbar(CMSToolbar): + _changed_admin_menu = None watch_models = [Page] # Helpers @@ -412,7 +413,7 @@ def change_language_menu(self): question=question % name, on_success=self.toolbar.REFRESH_PAGE) def change_admin_menu(self): - if self.has_page_change_permission(): + if not self._changed_admin_menu and self.has_page_change_permission(): admin_menu = self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER) url = admin_reverse('cms_page_changelist') # cms page admin params = {'language': self.toolbar.language} @@ -420,6 +421,8 @@ def change_admin_menu(self): params['page_id'] = self.page.pk url = add_url_parameters(url, params) admin_menu.add_sideframe_item(_('Pages'), url=url, position=0) + # Used to prevent duplicates + self._changed_admin_menu = True def add_page_menu(self): if self.page and self.has_page_change_permission(): diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py index acaae6f9b09..73113e94518 100644 --- a/cms/models/pagemodel.py +++ b/cms/models/pagemodel.py @@ -3,7 +3,6 @@ from os.path import join from django.conf import settings -from django.contrib.auth import get_permission_codename from django.contrib.sites.models import Site from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse diff --git a/cms/tests/toolbar.py b/cms/tests/toolbar.py index 8947324209f..b5d4e17da23 100644 --- a/cms/tests/toolbar.py +++ b/cms/tests/toolbar.py @@ -141,7 +141,7 @@ def test_no_page_staff(self): # Logo + admin-menu + logout self.assertEqual(len(items), 2, items) admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items() - self.assertEqual(len(admin_items), 9, admin_items) + self.assertEqual(len(admin_items), 10, admin_items) def test_no_page_superuser(self): request = self.get_page_request(None, self.get_superuser(), '/') @@ -152,7 +152,7 @@ def test_no_page_superuser(self): # Logo + edit-mode + admin-menu + logout self.assertEqual(len(items), 2) admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items() - self.assertEqual(len(admin_items), 10, admin_items) + self.assertEqual(len(admin_items), 11, admin_items) def test_anon(self): page = create_page('test', 'nav_playground.html', 'en') @@ -461,7 +461,7 @@ def test_double_menus(self): toolbar.post_template_populate() admin = toolbar.get_left_items()[0] lang = toolbar.get_left_items()[1] - self.assertEqual(len(admin.get_items()), 9) + self.assertEqual(len(admin.get_items()), 13) self.assertEqual(len(lang.get_items()), len(get_language_tuple(1))) @override_settings(CMS_PLACEHOLDER_CONF={'col_left': {'name': 'PPPP'}}) From 3941e426e4c71800841fb33d30e72e486a2a1032 Mon Sep 17 00:00:00 2001 From: Paulo Date: Tue, 12 Jan 2016 21:32:50 -0500 Subject: [PATCH 4/4] on 3.1 there's only 10 --- cms/tests/toolbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/tests/toolbar.py b/cms/tests/toolbar.py index b5d4e17da23..b6d9ff878a9 100644 --- a/cms/tests/toolbar.py +++ b/cms/tests/toolbar.py @@ -461,7 +461,7 @@ def test_double_menus(self): toolbar.post_template_populate() admin = toolbar.get_left_items()[0] lang = toolbar.get_left_items()[1] - self.assertEqual(len(admin.get_items()), 13) + self.assertEqual(len(admin.get_items()), 10) self.assertEqual(len(lang.get_items()), len(get_language_tuple(1))) @override_settings(CMS_PLACEHOLDER_CONF={'col_left': {'name': 'PPPP'}})