def test_slave_can_add_page_under_slave_home(self): with self.login_user_context(self.user_slave): # move to admin.py? # url = URL_CMS_PAGE_ADD + "?target=%d&position=last-child" % slave_page.pk # can he even access it over get? # response = self.client.get(url) # self.assertEqual(response.status_code, 200) # add page page = create_page("page", "nav_playground.html", "en", parent=self.slave_page, created_by=self.user_slave) # adds user_slave as page moderator for this page # public model shouldn't be available yet, because of the moderation # moderators and approval ok? # must not have public object yet self.assertFalse(page.publisher_public) self.assertObjectExist(Title.objects, slug="page") self.assertObjectDoesNotExist(Title.objects.public(), slug="page") self.assertTrue(user_can_publish_page(self.user_slave, page)) # publish as slave, published as user_master before publish_page(page, self.user_slave, 'en')
def has_publish_permission(self): if self.page: publish_permission = page_permissions.user_can_publish_page( self.request.user, page=self.page, site=self.current_site) else: publish_permission = False if publish_permission and self.statics: publish_permission = all( sp.has_publish_permission(self.request) for sp in self.dirty_statics) return publish_permission
def has_publish_permission(self): if not hasattr(self, 'publish_permission'): publish_permission = bool(self.page or self.statics) if self.page: publish_permission = page_permissions.user_can_publish_page(self.request.user, page=self.page) if self.statics: publish_permission &= all(sp.has_publish_permission(self.request) for sp in self.dirty_statics) self.publish_permission = publish_permission return self.publish_permission
def test_page_added_by_slave_can_be_published_by_user_master(self): # add page page = create_page("page", "nav_playground.html", "en", parent=self.slave_page, created_by=self.user_slave) # same as test_slave_can_add_page_under_slave_home # must not have public object yet self.assertFalse(page.publisher_public) self.assertTrue(user_can_publish_page(self.user_master, page)) # should be True user_master should have publish permissions for children as well publish_page(self.slave_page, self.user_master, 'en') page = publish_page(page, self.user_master, 'en') self.assertTrue(page.publisher_public_id)
def revert(self, request, **kwargs): page_pk = kwargs.get('page_pk') to_version_pk = kwargs.get('version_pk') language = request.GET.get('language') page = get_object_or_404(Page, pk=page_pk) page_version = get_object_or_404(PageVersion, pk=to_version_pk) # when the page_version you want to use as target and the current page mismatch # -> don't know why this should happen (but we can keep it as a guard) if not page_version.draft == page: raise Http404 # check if the current user is allowed to revert the page by checking the page publish permission user = get_current_user() if not user_can_publish_page(user, page_version.draft): messages.error( request, _('Missing permission to publish this page which is necessary for the rollback' )) prev = request.META.get('HTTP_REFERER') if prev: return redirect(prev) else: raise Http404 # Create a page_version of the page if it is dirty # prior to reverting try: PageVersion.create_version(page, language, version_parent=None, title='auto', comment='Auto before revert', version_id=None) except AssertionError as e: # AssertionError == page is not dirty pass revert_page(page_version, language) make_page_version_dirty(page, language) messages.info( request, _(u'You have succesfully reverted to {rev}').format( rev=page_version)) return self.render_close_frame()
def test_cached_permission_precedence(self): # refs - https://github.com/divio/django-cms/issues/6335 # cached page permissions should not override global permissions page = create_page( "test page", "nav_playground.html", "en", created_by=self.user_super, ) 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, "publish_page", []) can_publish = user_can_publish_page(self.user_normal, page) self.assertTrue(can_publish)
def add_page_menu(self): if self.page and self.has_page_change_permission(): edit_mode = self.toolbar.edit_mode refresh = self.toolbar.REFRESH_PAGE # menu for current page # NOTE: disabled if the current path is "deeper" into the # application's url patterns than its root. This is because # when the Content Manager is at the root of the app-hook, # some of the page options still make sense. current_page_menu = self.toolbar.get_or_create_menu( PAGE_MENU_IDENTIFIER, _('Page'), position=1, disabled=self.in_apphook() and not self.in_apphook_root()) new_page_params = {'edit': 1, 'position': 'last-child'} new_sub_page_params = {'edit': 1, 'position': 'last-child', 'target': self.page.pk} if self.page.parent_id: new_page_params['target'] = self.page.parent_id can_add_sibling_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page.parent, ) else: can_add_sibling_page = page_permissions.user_can_add_page( user=self.request.user, site=self.current_site, ) can_add_sub_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page, ) # page operations menu add_page_menu = current_page_menu.get_or_create_menu( PAGE_MENU_ADD_IDENTIFIER, _('Create Page'), ) app_page_url = admin_reverse('cms_page_add') add_page_menu_modal_items = ( (_('New Page'), new_page_params, can_add_sibling_page), (_('New Sub Page'), new_sub_page_params, can_add_sub_page), (_('Duplicate this Page'), {'copy_target': self.page.pk}, can_add_sibling_page) ) for title, params, has_perm in add_page_menu_modal_items: params.update(language=self.toolbar.language) add_page_menu.add_modal_item( title, url=add_url_parameters(app_page_url, params), disabled=not has_perm, ) # first break current_page_menu.add_break(PAGE_MENU_FIRST_BREAK) # page edit page_edit_url = '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') current_page_menu.add_link_item(_('Edit this Page'), disabled=edit_mode, url=page_edit_url) # page settings page_settings_url = admin_reverse('cms_page_change', args=(self.page.pk,)) page_settings_url = add_url_parameters(page_settings_url, language=self.toolbar.language) current_page_menu.add_modal_item(_('Page settings'), url=page_settings_url, disabled=not edit_mode, on_close=refresh) # advanced settings advanced_url = admin_reverse('cms_page_advanced', args=(self.page.pk,)) advanced_url = add_url_parameters(advanced_url, language=self.toolbar.language) advanced_disabled = not edit_mode or not self.page.has_advanced_settings_permission(self.request.user) current_page_menu.add_modal_item(_('Advanced settings'), url=advanced_url, disabled=advanced_disabled) # templates menu if self.toolbar.build_mode or edit_mode: templates_menu = current_page_menu.get_or_create_menu('templates', _('Templates')) action = admin_reverse('cms_page_change_template', args=(self.page.pk,)) for path, name in get_cms_setting('TEMPLATES'): active = self.page.template == path if path == TEMPLATE_INHERITANCE_MAGIC: templates_menu.add_break(TEMPLATE_MENU_BREAK) templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active, on_success=refresh) # page type page_type_url = admin_reverse('cms_page_add_page_type') page_type_url = add_url_parameters(page_type_url, copy_target=self.page.pk, language=self.toolbar.language) current_page_menu.add_modal_item(_('Save as Page Type'), page_type_url, disabled=not edit_mode) # second break current_page_menu.add_break(PAGE_MENU_SECOND_BREAK) # permissions if self.permissions_activated: permissions_url = admin_reverse('cms_page_permissions', args=(self.page.pk,)) permission_disabled = not edit_mode if not permission_disabled: permission_disabled = not page_permissions.user_can_change_page_permissions( user=self.request.user, page=self.page, ) current_page_menu.add_modal_item(_('Permissions'), url=permissions_url, disabled=permission_disabled) # dates settings dates_url = admin_reverse('cms_page_dates', args=(self.page.pk,)) current_page_menu.add_modal_item(_('Publishing dates'), url=dates_url, disabled=not edit_mode) # third break current_page_menu.add_break(PAGE_MENU_THIRD_BREAK) # navigation toggle nav_title = _('Hide in navigation') if self.page.in_navigation else _('Display in navigation') nav_action = admin_reverse('cms_page_change_innavigation', args=(self.page.pk,)) current_page_menu.add_ajax_item(nav_title, action=nav_action, disabled=not edit_mode, on_success=refresh) # publisher if self.title: if self.title.published: publish_title = _('Unpublish page') publish_url = admin_reverse('cms_page_unpublish', args=(self.page.pk, self.current_lang)) else: publish_title = _('Publish page') publish_url = admin_reverse('cms_page_publish_page', args=(self.page.pk, self.current_lang)) user_can_publish = user_can_publish_page(self.request.user, page=self.page) current_page_menu.add_ajax_item( publish_title, action=publish_url, disabled=not edit_mode or not user_can_publish, on_success=refresh, ) # revert to live current_page_menu.add_break(PAGE_MENU_FOURTH_BREAK) revert_action = admin_reverse('cms_page_revert_to_live', args=(self.page.pk, self.current_lang)) revert_question = _('Are you sure you want to revert to live?') # Only show this action if the page has pending changes and a public version is_enabled = self.page.is_dirty(self.current_lang) and self.page.publisher_public current_page_menu.add_ajax_item( _('Revert to live'), action=revert_action, question=revert_question, disabled=not is_enabled, on_success=refresh, extra_classes=('cms-toolbar-revert',), ) # last break current_page_menu.add_break(PAGE_MENU_LAST_BREAK) # delete delete_url = admin_reverse('cms_page_delete', args=(self.page.pk,)) delete_disabled = not edit_mode or not user_can_delete_page(self.request.user, page=self.page) on_delete_redirect_url = self.get_on_delete_redirect_url() current_page_menu.add_modal_item(_('Delete page'), url=delete_url, on_close=on_delete_redirect_url, disabled=delete_disabled)
def add_page_menu(self): if self.page: edit_mode = self.toolbar.edit_mode_active refresh = self.toolbar.REFRESH_PAGE can_change = user_can_change_page( user=self.request.user, page=self.page, site=self.current_site, ) # menu for current page # NOTE: disabled if the current path is "deeper" into the # application's url patterns than its root. This is because # when the Content Manager is at the root of the app-hook, # some of the page options still make sense. current_page_menu = self.toolbar.get_or_create_menu( PAGE_MENU_IDENTIFIER, _('Page'), position=1, disabled=self.in_apphook() and not self.in_apphook_root()) new_page_params = {'edit': 1} new_sub_page_params = {'edit': 1, 'parent_node': self.page.node_id} if self.page.is_page_type: add_page_url = admin_reverse('cms_pagetype_add') advanced_url = admin_reverse('cms_pagetype_advanced', args=(self.page.pk, )) page_settings_url = admin_reverse('cms_pagetype_change', args=(self.page.pk, )) duplicate_page_url = admin_reverse('cms_pagetype_duplicate', args=[self.page.pk]) else: add_page_url = admin_reverse('cms_page_add') advanced_url = admin_reverse('cms_page_advanced', args=(self.page.pk, )) page_settings_url = admin_reverse('cms_page_change', args=(self.page.pk, )) duplicate_page_url = admin_reverse('cms_page_duplicate', args=[self.page.pk]) can_add_root_page = page_permissions.user_can_add_page( user=self.request.user, site=self.current_site, ) if self.page.parent_page: new_page_params['parent_node'] = self.page.parent_page.node_id can_add_sibling_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page.parent_page, ) else: can_add_sibling_page = can_add_root_page can_add_sub_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page, ) # page operations menu add_page_menu = current_page_menu.get_or_create_menu( PAGE_MENU_ADD_IDENTIFIER, _('Create Page'), ) add_page_menu_modal_items = ( (_('New Page'), new_page_params, can_add_sibling_page), (_('New Sub Page'), new_sub_page_params, can_add_sub_page), ) for title, params, has_perm in add_page_menu_modal_items: params.update(language=self.toolbar.request_language) add_page_menu.add_modal_item( title, url=add_url_parameters(add_page_url, params), disabled=not has_perm, ) add_page_menu.add_modal_item( _('Duplicate this Page'), url=add_url_parameters( duplicate_page_url, {'language': self.toolbar.request_language}), disabled=not can_add_sibling_page, ) # first break current_page_menu.add_break(PAGE_MENU_FIRST_BREAK) # page edit page_edit_url = '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') current_page_menu.add_link_item(_('Edit this Page'), disabled=edit_mode, url=page_edit_url) # page settings page_settings_url = add_url_parameters( page_settings_url, language=self.toolbar.request_language) settings_disabled = not edit_mode or not can_change current_page_menu.add_modal_item(_('Page settings'), url=page_settings_url, disabled=settings_disabled, on_close=refresh) # advanced settings advanced_url = add_url_parameters( advanced_url, language=self.toolbar.request_language) can_change_advanced = self.page.has_advanced_settings_permission( self.request.user) advanced_disabled = not edit_mode or not can_change_advanced current_page_menu.add_modal_item(_('Advanced settings'), url=advanced_url, disabled=advanced_disabled) # templates menu if edit_mode: if self.page.is_page_type: action = admin_reverse('cms_pagetype_change_template', args=(self.page.pk, )) else: action = admin_reverse('cms_page_change_template', args=(self.page.pk, )) if can_change_advanced: templates_menu = current_page_menu.get_or_create_menu( 'templates', _('Templates'), disabled=not can_change, ) for path, name in get_cms_setting('TEMPLATES'): active = self.page.template == path if path == TEMPLATE_INHERITANCE_MAGIC: templates_menu.add_break(TEMPLATE_MENU_BREAK) templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active, on_success=refresh) # page type if not self.page.is_page_type: page_type_url = admin_reverse('cms_pagetype_add') page_type_url = add_url_parameters( page_type_url, source=self.page.pk, language=self.toolbar.request_language) page_type_disabled = not edit_mode or not can_add_root_page current_page_menu.add_modal_item(_('Save as Page Type'), page_type_url, disabled=page_type_disabled) # second break current_page_menu.add_break(PAGE_MENU_SECOND_BREAK) # permissions if self.permissions_activated: permissions_url = admin_reverse('cms_page_permissions', args=(self.page.pk, )) permission_disabled = not edit_mode if not permission_disabled: permission_disabled = not page_permissions.user_can_change_page_permissions( user=self.request.user, page=self.page, ) current_page_menu.add_modal_item(_('Permissions'), url=permissions_url, disabled=permission_disabled) if not self.page.is_page_type: # dates settings dates_url = admin_reverse('cms_page_dates', args=(self.page.pk, )) current_page_menu.add_modal_item( _('Publishing dates'), url=dates_url, disabled=(not edit_mode or not can_change), ) # third break current_page_menu.add_break(PAGE_MENU_THIRD_BREAK) # navigation toggle nav_title = _( 'Hide in navigation') if self.page.in_navigation else _( 'Display in navigation') nav_action = admin_reverse('cms_page_change_innavigation', args=(self.page.pk, )) current_page_menu.add_ajax_item( nav_title, action=nav_action, disabled=(not edit_mode or not can_change), on_success=refresh, ) # publisher if self.title and not self.page.is_page_type: if self.title.published: publish_title = _('Unpublish page') publish_url = admin_reverse('cms_page_unpublish', args=(self.page.pk, self.current_lang)) else: publish_title = _('Publish page') publish_url = admin_reverse('cms_page_publish_page', args=(self.page.pk, self.current_lang)) user_can_publish = user_can_publish_page(self.request.user, page=self.page) current_page_menu.add_ajax_item( publish_title, action=publish_url, disabled=not edit_mode or not user_can_publish, on_success=refresh, ) if self.current_lang and not self.page.is_page_type: # revert to live current_page_menu.add_break(PAGE_MENU_FOURTH_BREAK) revert_action = admin_reverse('cms_page_revert_to_live', args=(self.page.pk, self.current_lang)) revert_question = _('Are you sure you want to revert to live?') # Only show this action if the page has pending changes and a public version is_enabled = (edit_mode and can_change and self.page.is_dirty(self.current_lang) and self.page.publisher_public) current_page_menu.add_ajax_item( _('Revert to live'), action=revert_action, question=revert_question, disabled=not is_enabled, on_success=refresh, extra_classes=('cms-toolbar-revert', ), ) # last break current_page_menu.add_break(PAGE_MENU_LAST_BREAK) # delete if self.page.is_page_type: delete_url = admin_reverse('cms_pagetype_delete', args=(self.page.pk, )) else: delete_url = admin_reverse('cms_page_delete', args=(self.page.pk, )) delete_disabled = not edit_mode or not user_can_delete_page( self.request.user, page=self.page) on_delete_redirect_url = self.get_on_delete_redirect_url() current_page_menu.add_modal_item(_('Delete page'), url=delete_url, on_close=on_delete_redirect_url, disabled=delete_disabled)
def add_page_menu(self): if self.page and self.has_page_change_permission(): edit_mode = self.toolbar.edit_mode refresh = self.toolbar.REFRESH_PAGE # menu for current page # NOTE: disabled if the current path is "deeper" into the # application's url patterns than its root. This is because # when the Content Manager is at the root of the app-hook, # some of the page options still make sense. current_page_menu = self.toolbar.get_or_create_menu( PAGE_MENU_IDENTIFIER, _('Page'), position=1, disabled=self.in_apphook() and not self.in_apphook_root()) new_page_params = {'edit': 1, 'position': 'last-child'} new_sub_page_params = { 'edit': 1, 'position': 'last-child', 'target': self.page.pk } if self.page.parent_id: new_page_params['target'] = self.page.parent_id can_add_sibling_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page.parent, ) else: can_add_sibling_page = page_permissions.user_can_add_page( user=self.request.user, site=self.current_site, ) can_add_sub_page = page_permissions.user_can_add_subpage( user=self.request.user, target=self.page, ) # page operations menu add_page_menu = current_page_menu.get_or_create_menu( PAGE_MENU_ADD_IDENTIFIER, _('Create Page'), ) app_page_url = admin_reverse('cms_page_add') add_page_menu_modal_items = ((_('New Page'), new_page_params, can_add_sibling_page), (_('New Sub Page'), new_sub_page_params, can_add_sub_page), (_('Duplicate this Page'), { 'copy_target': self.page.pk }, can_add_sibling_page)) for title, params, has_perm in add_page_menu_modal_items: params.update(language=self.toolbar.language) add_page_menu.add_modal_item( title, url=add_url_parameters(app_page_url, params), disabled=not has_perm, ) # first break current_page_menu.add_break(PAGE_MENU_FIRST_BREAK) # page edit page_edit_url = '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') current_page_menu.add_link_item(_('Edit this Page'), disabled=edit_mode, url=page_edit_url) # page settings page_settings_url = admin_reverse('cms_page_change', args=(self.page.pk, )) page_settings_url = add_url_parameters( page_settings_url, language=self.toolbar.language) current_page_menu.add_modal_item(_('Page settings'), url=page_settings_url, disabled=not edit_mode, on_close=refresh) # advanced settings advanced_url = admin_reverse('cms_page_advanced', args=(self.page.pk, )) advanced_url = add_url_parameters(advanced_url, language=self.toolbar.language) advanced_disabled = not edit_mode or not self.page.has_advanced_settings_permission( self.request.user) current_page_menu.add_modal_item(_('Advanced settings'), url=advanced_url, disabled=advanced_disabled) # templates menu if self.toolbar.build_mode or edit_mode: templates_menu = current_page_menu.get_or_create_menu( 'templates', _('Templates')) action = admin_reverse('cms_page_change_template', args=(self.page.pk, )) for path, name in get_cms_setting('TEMPLATES'): active = self.page.template == path if path == TEMPLATE_INHERITANCE_MAGIC: templates_menu.add_break(TEMPLATE_MENU_BREAK) templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active, on_success=refresh) # page type page_type_url = admin_reverse('cms_page_add_page_type') page_type_url = add_url_parameters(page_type_url, copy_target=self.page.pk, language=self.toolbar.language) current_page_menu.add_modal_item(_('Save as Page Type'), page_type_url, disabled=not edit_mode) # second break current_page_menu.add_break(PAGE_MENU_SECOND_BREAK) # permissions if self.permissions_activated: permissions_url = admin_reverse('cms_page_permissions', args=(self.page.pk, )) permission_disabled = not edit_mode if not permission_disabled: permission_disabled = not page_permissions.user_can_change_page_permissions( user=self.request.user, page=self.page, ) current_page_menu.add_modal_item(_('Permissions'), url=permissions_url, disabled=permission_disabled) # dates settings dates_url = admin_reverse('cms_page_dates', args=(self.page.pk, )) current_page_menu.add_modal_item(_('Publishing dates'), url=dates_url, disabled=not edit_mode) # third break current_page_menu.add_break(PAGE_MENU_THIRD_BREAK) # navigation toggle nav_title = _( 'Hide in navigation') if self.page.in_navigation else _( 'Display in navigation') nav_action = admin_reverse('cms_page_change_innavigation', args=(self.page.pk, )) current_page_menu.add_ajax_item(nav_title, action=nav_action, disabled=not edit_mode, on_success=refresh) # publisher if self.title: if self.title.published: publish_title = _('Unpublish page') publish_url = admin_reverse('cms_page_unpublish', args=(self.page.pk, self.current_lang)) else: publish_title = _('Publish page') publish_url = admin_reverse('cms_page_publish_page', args=(self.page.pk, self.current_lang)) user_can_publish = user_can_publish_page(self.request.user, page=self.page) current_page_menu.add_ajax_item( publish_title, action=publish_url, disabled=not edit_mode or not user_can_publish, on_success=refresh, ) # last break current_page_menu.add_break(PAGE_MENU_LAST_BREAK) # delete delete_url = admin_reverse('cms_page_delete', args=(self.page.pk, )) delete_disabled = not edit_mode or not user_can_delete_page( self.request.user, page=self.page) on_delete_redirect_url = self.get_on_delete_redirect_url() current_page_menu.add_modal_item(_('Delete page'), url=delete_url, on_close=on_delete_redirect_url, disabled=delete_disabled)