def test_add_page_twice(self): user1 = self._create_user("user1", is_staff=True, is_superuser=False, add_default_permissions=True) home = create_page("home", "nav_playground.html", "en", published=True) home.set_as_homepage() assign_user_to_page(home, user1, grant_on=ACCESS_PAGE_AND_DESCENDANTS, can_add=True, can_change=True, can_publish=True) with self.login_user_context(user1): response = self.client.post( f'{URL_CMS_PAGE_ADD}?parent_node={home.node.pk}', self.get_new_page_data(parent_id=home.node.pk)) self.assertEqual(response.status_code, 302) child = home.reload().get_child_pages().first() self.assertIsNotNone(child) # Ignore cached_func User = get_user_model() user1 = User.objects.get(pk=user1.pk) self.assertTrue(user_can_add_subpage(user1, child))
def clean_parent_node(self): # Check to see if this user has permissions to make this page. We've # already checked this when producing a list of wizard entries, but this # is to prevent people from possible form-hacking. if self.page and self.sub_page_form: # User is adding a page which will be a direct # child of the current page. parent_page = self.page elif self.page and self.page.parent_page: # User is adding a page which will be a right # sibling to the current page. parent_page = self.page.parent_page else: parent_page = None if parent_page: has_perm = user_can_add_subpage(self.user, target=parent_page) else: has_perm = user_can_add_page(self.user) if not has_perm: message = gettext( 'You don\'t have the permissions required to add a page.') raise ValidationError(message) return parent_page.node if parent_page else None
def user_has_add_permission(self, user, page=None, **kwargs): if page and page.parent_id: # User is adding a page which will be a right # sibling to the current page. has_perm = user_can_add_subpage(user, target=page.parent) else: has_perm = user_can_add_page(user) return has_perm
def populate(self): super().populate() if not self.page: # Nothing to do return if user_can_change_page(user=self.request.user, page=self.page) and user_can_add_subpage( self.request.user, self.page): # Add snapshot menu item only on course pages try: course = Course.objects.only("id").get( extended_object=self.page) except Course.DoesNotExist: return # Course snapshots can not be snapshotted if self.page.parent_page: try: self.page.parent_page.course except Course.DoesNotExist: pass else: return url = admin_reverse("cms_course_snapshot", kwargs={"course_id": course.id}) edit_mode_inactive = not self.toolbar.edit_mode_active page_menu = self.toolbar.get_or_create_menu("page") # Create the new menu item as an Ajax call page_menu.add_ajax_item( _("Snapshot this page..."), action=url, data={}, question=_( "This will place a copy of this page as its child and move all its course" "runs as children of its new copy."), on_success=self.toolbar.REFRESH_PAGE, disabled=edit_mode_inactive, position=PAGE_EXTENSION_TOOLBAR_ITEM_POSITION - 1, )
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 actions_menu(self, request, object_id): page = get_object_or_404(self.model, pk=object_id) paste_enabled = request.GET.get('has_copy') or request.GET.get( 'has_cut') can_change_advanced_settings = self.has_change_advanced_settings_permission( request, obj=page) has_change_permissions_permission = self.has_change_permissions_permission( request, obj=page) is_bin = page.title_set.filter( title__startswith=BIN_NAMING_PREFIX).count() > 0 if is_bin: context = { 'page': page, 'page_is_restricted': True, 'paste_enabled': False, 'has_add_permission': False, 'has_change_permission': False, 'has_change_advanced_settings_permission': False, 'has_change_permissions_permission': False, 'has_move_page_permission': False, 'has_delete_permission': self.has_delete_permission(request, obj=page), 'CMS_PERMISSION': False, } else: context = { 'page': page, 'page_is_restricted': page.has_view_restrictions(), 'paste_enabled': paste_enabled, 'has_add_permission': page_permissions.user_can_add_subpage(request.user, target=page), 'has_change_permission': self.has_change_permission(request, obj=page), 'has_change_advanced_settings_permission': can_change_advanced_settings, 'has_change_permissions_permission': has_change_permissions_permission, 'has_move_page_permission': self.has_move_page_permission(request, obj=page), 'has_delete_permission': self.has_delete_permission(request, obj=page), 'CMS_PERMISSION': get_cms_setting('PERMISSION'), } return render(request, "admin/cms/page/tree/actions_dropdown.html", context)
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)
def user_has_add_permission(self, user, page=None, **kwargs): if not page or page.application_urls: # We can't really add a sub-page to a non-existent page. Or to an # app-hooked page. return False return user_can_add_subpage(user, target=page)
def save(self, **kwargs): from cms.api import create_page, add_plugin # Check to see if this user has permissions to make this page. We've # already checked this when producing a list of wizard entries, but this # is to prevent people from possible form-hacking. if 'sub_page' in self.cleaned_data: sub_page = self.cleaned_data['sub_page'] else: sub_page = False if self.page and sub_page: # User is adding a page which will be a direct # child of the current page. position = 'last-child' parent = self.page has_perm = user_can_add_subpage(self.user, target=parent) elif self.page and self.page.parent_id: # User is adding a page which will be a right # sibling to the current page. position = 'last-child' parent = self.page.parent has_perm = user_can_add_subpage(self.user, target=parent) else: parent = None position = 'last-child' has_perm = user_can_add_page(self.user) if not has_perm: raise NoPermissionsException( _(u"User does not have permission to add page.")) page = create_page( title=self.cleaned_data['title'], slug=self.cleaned_data['slug'], template=get_cms_setting('PAGE_WIZARD_DEFAULT_TEMPLATE'), language=self.language_code, created_by=smart_text(self.user), parent=parent, position=position, in_navigation=True, published=False ) page_type = self.cleaned_data.get("page_type") if page_type: copy_target = Page.objects.filter(pk=page_type).first() else: copy_target = None if copy_target: # If the user selected a page type, copy that. if not copy_target.has_view_permission(self.user): raise PermissionDenied() # Copy page attributes copy_target._copy_attributes(page, clean=True) page.save() # Copy contents (for each language) for lang in copy_target.get_languages(): copy_target._copy_contents(page, lang) # Copy extensions from cms.extensions import extension_pool extension_pool.copy_extensions(copy_target, page) else: # If the user provided content, then use that instead. content = self.cleaned_data.get('content') plugin_type = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN') plugin_body = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN_BODY') slot = get_cms_setting('PAGE_WIZARD_CONTENT_PLACEHOLDER') if plugin_type in plugin_pool.plugins and plugin_body: if content and permissions.has_plugin_permission( self.user, plugin_type, "add"): placeholder = self.get_placeholder(page, slot=slot) if placeholder: opts = { 'placeholder': placeholder, 'plugin_type': plugin_type, 'language': self.language_code, plugin_body: content, } add_plugin(**opts) # is it home? publish it right away if not self.page and page.is_home: page.publish(self.language_code) return page
def snapshot_course(page, user, simulate_only=False): """ Snapshotting a course is making a copy of the course page with all its permissions and extensions, and placing the copy as the first child of the page being snapshotted, then moving all the course run of the page being snapshotted as children of the new snapshot so we keep record of the course as it was when these course runs were played. """ if not page.publisher_is_draft: raise PermissionDenied("You can't snapshot a public page.") # If the page has a parent that is a course page, it is a snapshot and should therefore # not be allowed to be itself snapshotted. if page.parent_page: try: page.parent_page.course except Course.DoesNotExist: pass else: raise PermissionDenied(_("You can't snapshot a snapshot.")) site = page.node.site # User can only snapshot pages he can change can_snapshot = page_permissions.user_can_change_page(user, page, site) if can_snapshot: # User can only snapshot a page if he has the permission to add a page under it. can_snapshot = page_permissions.user_can_add_subpage(user, page, site) if not can_snapshot: raise PermissionDenied( _("You don't have sufficient permissions to snapshot this page.")) if simulate_only: return None # Copy the page as its own child with its extension. # Titles are set to a timestamp in each language of the original page snapshot_page = page.copy(site, parent_node=page.node, translations=False, extensions=True) # The snapshot title and slug is set with the date and time of snapshot. It is # published only in languages for which the original course page was published. now = timezone.now() for language in page.get_languages(): base = page.get_path(language) title = page.get_title(language) version = _(f"Archived on {now:%Y-%m-%d %H:%M:%S}") slug = slugify(version) create_title( language=language, menu_title=version, title=_(f"{title:s} ({version!s})"), slug=slug, path=f"{base!s}/{slug!s}" if base else slug, page=snapshot_page, ) if page.is_published(language) is True: snapshot_page.publish(language) # Change the existing course runs to be related children of the snapshot # Their publication status will be respected for run in page.course.runs.all(): run.direct_course = snapshot_page.course run.save() if page.publisher_public and snapshot_page.publisher_public: for run in page.publisher_public.course.runs.all(): run.direct_course = snapshot_page.publisher_public.course run.save() return snapshot_page
def save(self, **kwargs): from cms.api import create_page, add_plugin # Check to see if this user has permissions to make this page. We've # already checked this when producing a list of wizard entries, but this # is to prevent people from possible form-hacking. if 'sub_page' in self.cleaned_data: sub_page = self.cleaned_data['sub_page'] else: sub_page = False if self.page and sub_page: # User is adding a page which will be a direct # child of the current page. position = 'last-child' parent = self.page has_perm = user_can_add_subpage(self.user, target=parent) elif self.page and self.page.parent_id: # User is adding a page which will be a right # sibling to the current page. position = 'last-child' parent = self.page.parent has_perm = user_can_add_subpage(self.user, target=parent) else: parent = None position = 'last-child' has_perm = user_can_add_page(self.user) if not has_perm: raise NoPermissionsException( _(u"User does not have permission to add page.")) page = create_page( title=self.cleaned_data['title'], slug=self.cleaned_data['slug'], template=get_cms_setting('PAGE_WIZARD_DEFAULT_TEMPLATE'), language=self.language_code, created_by=smart_text(self.user), parent=parent, position=position, in_navigation=True, published=False ) page_type = self.cleaned_data.get("page_type") if page_type: copy_target = Page.objects.filter(pk=page_type).first() else: copy_target = None if copy_target: # If the user selected a page type, copy that. if not copy_target.has_view_permission(self.user): raise PermissionDenied() # Copy page attributes copy_target._copy_attributes(page, clean=True) page.save() # Copy contents (for each language) for lang in copy_target.get_languages(): copy_target._copy_contents(page, lang) # Copy extensions from cms.extensions import extension_pool extension_pool.copy_extensions(copy_target, page) else: # If the user provided content, then use that instead. content = self.cleaned_data.get('content') plugin_type = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN') plugin_body = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN_BODY') slot = get_cms_setting('PAGE_WIZARD_CONTENT_PLACEHOLDER') if plugin_type in plugin_pool.plugins and plugin_body: if content and permissions.has_plugin_permission( self.user, plugin_type, "add"): placeholder = self.get_placeholder(page, slot=slot) if placeholder: opts = { 'placeholder': placeholder, 'plugin_type': plugin_type, 'language': self.language_code, plugin_body: content, } add_plugin(**opts) # is it the first page? publish it right away if not self.page and Page.objects.filter(site_id=page.site_id).count() == 1: page.publish(self.language_code) Page.set_homepage(page, user=self.user) return page
def snapshot_course(page, user, simulate_only=False): """ Snapshotting a course is making a copy of the course page with all its permissions and extensions, and placing the copy as the first child of the page being snapshotted, then moving all the course run of the page being snapshotted as children of the new snapshot so we keep record of the course as it was when these course runs were played. """ if not page.publisher_is_draft: raise PermissionDenied("You can't snapshot a public page.") # If the page has a parent that is a course page, it is a snapshot and should therefore # not be allowed to be itself snapshotted. if page.parent_page: try: page.parent_page.course except Course.DoesNotExist: pass else: raise PermissionDenied(_("You can't snapshot a snapshot.")) site = page.node.site # User can only snapshot pages he can see can_snapshot = page_permissions.user_can_change_page(user, page, site) if can_snapshot: # User can only snapshot a page if he has the permission to add a page under it. can_snapshot = page_permissions.user_can_add_subpage(user, page, site) if not can_snapshot: raise PermissionDenied( _("You don't have sufficient permissions to snapshot this page.")) if simulate_only: return None # Copy the page as its own child with its extension. # Titles are set to a timestamp in each language of the original page snapshot_page = page.copy(site, parent_node=page.node, translations=False, extensions=True) # The snapshot title and slug is set to a timestamp of the time of snapshot. It is # published only in languages for which the original course page was published. for language in page.get_languages(): base = page.get_path(language) timestamp = str(int(time.time())) snapshot_title = _("Snapshot of {:s}").format(page.get_title(language)) create_title( language=language, menu_title=timestamp, title="{:s} - {:s}".format(timestamp, snapshot_title), slug=timestamp, path="{:s}/{:s}".format(base, timestamp) if base else timestamp, page=snapshot_page, ) if page.is_published(language) is True: snapshot_page.publish(language) # Move the existing course run subpages as children of the snapshot # Their publication status will be respected for subpage in page.get_child_pages().filter(courserun__isnull=False): subpage.move_page(snapshot_page.node, position="last-child") return snapshot_page
def actions_menu(self, request, object_id, extra_context=None): page = self.get_object(request, object_id=object_id) if page is None: raise self._get_404_exception(object_id) site = self.get_site(request) paste_enabled = request.GET.get('has_copy') or request.GET.get( 'has_cut') context = { 'page': page, 'node': page.node, 'opts': self.opts, 'site': site, 'page_is_restricted': page.has_view_restrictions(site), 'paste_enabled': paste_enabled, 'has_add_permission': page_permissions.user_can_add_subpage(request.user, target=page), 'has_copy_page_permission': page_permissions.user_can_view_page_draft(request.user, page, site=site), 'has_change_permission': self.has_change_permission(request, obj=page), 'has_change_advanced_settings_permission': self.has_change_advanced_settings_permission(request, obj=page), '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), 'CMS_PERMISSION': get_cms_setting('PERMISSION'), } # Bin/Version page # ---------------- page_query = page.get_root().title_set.filter( title__in=[BIN_ROOT_TITLE, VERSION_ROOT_TITLE]) is_in_bin = page_query.filter(title=BIN_ROOT_TITLE).exists() is_version = page_query.filter(title=VERSION_ROOT_TITLE).exists() is_version_root = (page.title_set.filter(title__in=[BIN_ROOT_TITLE, VERSION_ROOT_TITLE]) | \ page.title_set.filter(title__startswith='.DELETED')).exists() if is_in_bin or is_version: context.update({ 'page_is_restricted': True, 'paste_enabled': False, 'has_add_permission': False, 'has_change_permission': False, 'has_change_advanced_settings_permission': False, 'has_change_permissions_permission': False, 'has_copy_page_permission': not is_version_root, 'has_move_page_permission': False, 'has_delete_permission': False, 'CMS_PERMISSION': False, }) # ---------------- if extra_context: context.update(extra_context) return render(request, self.actions_menu_template, context)