def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check global permissions if CMS_PERMISSIONS is active if get_cms_setting('PERMISSION'): has_global_current_page_change_permission = user_can_change_page(self.request.user, page=self.page) else: has_global_current_page_change_permission = False # check if user has page edit permission can_change = self.request.current_page and user_can_change_page(self.request.user, page=self.page) if has_global_current_page_change_permission or can_change: try: menu_icons = MenuIcon.objects.get(extended_object_id=self.page.id) except MenuIcon.DoesNotExist: menu_icons = None try: if menu_icons: url = reverse('admin:menu_icons_menuicon_change', args=(menu_icons.pk,)) else: url = reverse('admin:menu_icons_menuicon_add') + '?extended_object=%s' % self.page.pk except NoReverseMatch: # not in urls pass not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page') current_page_menu.add_modal_item(_('Menu Icon'), url=url, disabled=not_edit_mode, position=0)
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check if user has page edit permission if user_can_change_page(user=self.request.user, page=self.page): try: extension = CSSExtension.objects.get( extended_object_id=self.page.id) except CSSExtension.DoesNotExist: extension = None try: if extension: url = reverse("admin:cms_extensions_cssextension_change", args=(extension.pk, )) else: url = reverse("admin:cms_extensions_cssextension_add") url = f"{url}?extended_object={self.page.pk}" except NoReverseMatch: # not in urls pass else: not_edit_mode = not self.toolbar.edit_mode_active current_page_menu = self.toolbar.\ get_or_create_menu("page") current_page_menu.add_modal_item(_("CSS"), url=url, disabled=not_edit_mode)
def _save_model(self, request, obj, form, change): """ djangocms-cms/extensions/admin.py, last changed in: django-cms/django-cms@61e7756a79de0db9671417b44235bbf8866c3c9f Ensure that the current page content object can be retrieved. A draft object will return an empty set by default hence why we have to remove the query manager here! """ if not change and 'extended_object' in request.GET: extended_object = PageContent._original_manager.get( pk=request.GET['extended_object']) obj.extended_object = extended_object title = extended_object else: title = obj.extended_object if not user_can_change_page(request.user, page=title.page): raise PermissionDenied() super(TitleExtensionAdmin, self).save_model(request, obj, form, change) # Ensure that we update the version modified date of the attached version if title: _update_modified(title)
def populate(self): """ When visiting a page that is linked to a page extension, show an item in the toolbar only to users who have the permission to update the page. Clicking on this menu item will open the admin page of the page extension. Note: We don't want to show a link to create a new page extension on a page that does not have it yet. For clarity, we choose to only create page extensions transparently via the page creation wizard. """ # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return if user_can_change_page(user=self.request.user, page=self.page): page_extension, admin_url = self.get_page_extension_admin() if page_extension: edit_mode_inactive = not self.toolbar.edit_mode_active page_menu = self.toolbar.get_or_create_menu("page") # Create the new menu item as a modal page_menu.add_modal_item( _("{:s} settings").format(self.model.__name__), url=admin_url, disabled=edit_mode_inactive, position=PAGE_EXTENSION_TOOLBAR_ITEM_POSITION, )
def populate(self): page = get_page_draft(self.request.current_page) if not page or not user_can_change_page(self.request.user, page=page): return current_page_menu = self.toolbar.get_or_create_menu('page') position = self.get_position(current_page_menu) file_formats = FILE_FORMATS.values() if len(file_formats) == 1: menu = current_page_menu else: menu = current_page_menu.get_or_create_menu( 'export-page', _('Export'), position=position) for file_format in file_formats: label = _('Export to {ext}').format(ext='.' + file_format.ext) url = reverse('export-page:cms_page', kwargs={ 'page_pk': page.pk, 'file_format': file_format.name}) menu.add_link_item(label, url=url, position=position) current_page_menu.add_break('export-page-break', position=position)
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return if user_can_change_page(self.request.user, page=self.page): try: mytitleextension = MyTitleExtension.objects.get( extended_object_id=self.page.id) except MyTitleExtension.DoesNotExist: mytitleextension = None try: if mytitleextension: url = admin_reverse('extensionapp_mytitleextension_change', args=(mytitleextension.pk, )) else: url = admin_reverse( 'extensionapp_mytitleextension_add' ) + '?extended_object=%s' % self.page.pk except NoReverseMatch: # not in urls pass else: not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page') current_page_menu.add_modal_item(_('Title Extension'), url=url, disabled=not_edit_mode)
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return if user_can_change_page(user=self.request.user, page=self.page): try: page_extension = PageDetailExtension.objects.get( extended_object_id=self.page.id) except PageDetailExtension.DoesNotExist: page_extension = None try: if page_extension: url = reverse('admin:api_pagedetailextension_change', args=(page_extension.pk, )) else: url = reverse('admin:api_pagedetailextension_add' ) + '?extended_object=%s' % self.page.pk test = url except NoReverseMatch: # not in urls pass else: not_edit_mode = not self.toolbar.edit_mode_active current_page_menu = self.toolbar.get_or_create_menu('page') current_page_menu.add_modal_item(_('Page Extention'), url=url, disabled=not_edit_mode)
def change_language_menu(self): if self.toolbar.edit_mode_active and self.page: can_change = page_permissions.user_can_change_page( user=self.request.user, page=self.page, site=self.current_site, ) else: can_change = False if can_change: language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER) if not language_menu: return None languages = get_language_dict(self.current_site.pk) remove = [(code, languages.get(code, code)) for code in self.page.get_languages() if code in languages] add = [l for l in languages.items() if l not in remove] if add: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) add_plugins_menu = language_menu.get_or_create_menu( '{0}-add'.format(LANGUAGE_MENU_IDENTIFIER), _('Add Translation')) page_add_url = admin_reverse('cms_pagecontent_add') for code, name in add: url = add_url_parameters(page_add_url, cms_page=self.page.pk, language=code) add_plugins_menu.add_modal_item(name, url=url)
def add_view(self, request, form_url='', extra_context=None): language = request.GET.get('language') draft_pk = request.GET.get('draft') page = get_object_or_404(Page, pk=draft_pk) # check if the current user may view the revision # -> if the user may see the page user = get_current_user() if not user_can_change_page(user, page): messages.error( request, _('Missing permission to edit this page which is necessary in order to create a ' 'page version.')) prev = request.META.get('HTTP_REFERER') if prev: return redirect(prev) else: raise Http404 if page.page_versions.filter(active=True, dirty=False, language=language).exists(): messages.info(request, _('This page already has a saved revision.')) return self.render_close_frame() return super(PageVersionAdmin, self).add_view(request, form_url=form_url, extra_context=extra_context)
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return if user_can_change_page(self.request.user, page=self.page): try: mypageextension = MyPageExtension.objects.get(extended_object_id=self.page.id) except MyPageExtension.DoesNotExist: mypageextension = None try: if mypageextension: url = admin_reverse('extensionapp_mypageextension_change', args=(mypageextension.pk,)) else: url = admin_reverse('extensionapp_mypageextension_add') + '?extended_object=%s' % self.page.pk except NoReverseMatch: # not in urls pass else: not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page') current_page_menu.add_modal_item(_('Page Extension'), url=url, disabled=not_edit_mode)
def has_delete_permission(self, request, obj=None): """Allow change only if the user is allowed to change the related course page.""" if obj and getattr(settings, "CMS_PERMISSION", False): course_page = obj.direct_course.extended_object if not page_permissions.user_can_change_page( request.user, course_page, course_page.node.site): return False return super().has_delete_permission(request, obj=obj)
def change_language_menu(self): if self.toolbar.edit_mode_active and self.page: can_change = page_permissions.user_can_change_page( user=self.request.user, page=self.page, site=self.current_site) else: can_change = False if can_change: language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER) if not language_menu: return None languages = get_language_dict(self.current_site.pk) remove = [(code, languages.get(code, code)) for code in self.page.get_languages() if code in languages] add = [code for code in languages.items() if code not in remove] copy = [(code, name) for code, name in languages.items() if code != self.current_lang and (code, name) in remove] if add: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) add_plugins_menu = language_menu.get_or_create_menu( "{0}-add".format(LANGUAGE_MENU_IDENTIFIER), _("Add Translation")) page_add_url = admin_reverse("cms_pagecontent_add") for code, name in add: url = add_url_parameters(page_add_url, cms_page=self.page.pk, language=code) add_plugins_menu.add_modal_item(name, url=url) if copy: copy_plugins_menu = language_menu.get_or_create_menu( '{0}-copy'.format(LANGUAGE_MENU_IDENTIFIER), _('Copy all plugins')) title = _('from %s') question = _( 'Are you sure you want to copy all plugins from %s?') for code, name in copy: # Get the Draft or Published PageContent. page_content = self.get_page_content(language=code) page_copy_url = admin_reverse( 'cms_pagecontent_copy_language', args=(page_content.pk, )) copy_plugins_menu.add_ajax_item( title % name, action=page_copy_url, data={ 'source_language': code, 'target_language': self.current_lang }, question=question % name, on_success=self.toolbar.REFRESH_PAGE)
def populate(self): if not self.toolbar.edit_mode: return cms_page = get_page_draft(self.request.current_page) if not cms_page or user_can_change_page(self.request.user, cms_page): self.active_operation = self.get_active_operation() self.add_buttons()
def save_model(self, request, obj, form, change): if not change and "extended_object" in request.GET: obj.extended_object = Title.objects.get(pk=request.GET["extended_object"]) title = Title.objects.get(pk=request.GET["extended_object"]) else: title = obj.extended_object if not user_can_change_page(request.user, page=title.page): raise PermissionDenied() super(TitleExtensionAdmin, self).save_model(request, obj, form, change)
def get_page_from_request(request, use_path=None): """ Gets the current page from a request object. URLs can be of the following form (this should help understand the code): http://server.whatever.com/<some_path>/"pages-root"/some/page/slug <some_path>: This can be anything, and should be stripped when resolving pages names. This means the CMS is not installed at the root of the server's URLs. "pages-root" This is the root of Django urls for the CMS. It is, in essence an empty page slug (slug == '') The page slug can then be resolved to a Page model object """ # The following is used by cms.middleware.page.CurrentPageMiddleware if hasattr(request, '_current_page_cache'): return request._current_page_cache draft = use_draft(request) preview = 'preview' in request.GET # If use_path is given, someone already did the path cleaning if use_path is not None: path = use_path else: path = request.path_info pages_root = unquote(reverse("pages-root")) # otherwise strip off the non-cms part of the URL if is_installed('django.contrib.admin'): admin_base = admin_reverse('index') else: admin_base = None if path.startswith(pages_root) and (not admin_base or not path.startswith(admin_base)): path = path[len(pages_root):] # and strip any final slash if path.endswith("/"): path = path[:-1] page = get_page_from_path(path, preview, draft) if draft and page and not user_can_change_page(request.user, page): page = get_page_from_path(path, preview, draft=False) # For public pages we check if any parent is hidden due to published dates # In this case the selected page is not reachable if page and not draft: ancestors = page.get_ancestors().filter( Q(publication_date__gt=timezone.now()) | Q(publication_end_date__lt=timezone.now()), ) if ancestors.exists(): page = None request._current_page_cache = page return page
def save_model(self, request, obj, form, change): if not change and 'extended_object' in request.GET: obj.extended_object = Title.objects.get( pk=request.GET['extended_object']) title = Title.objects.get(pk=request.GET['extended_object']) else: title = obj.extended_object if not user_can_change_page(request.user, page=title.page): raise PermissionDenied() super().save_model(request, obj, form, change)
def save_model(self, request, obj, form, change): if not change and 'extended_object' in request.GET: obj.extended_object = Page.objects.get( pk=request.GET['extended_object']) page = Page.objects.get(pk=request.GET['extended_object']) else: page = obj.extended_object if not user_can_change_page(request.user, page): raise PermissionDenied() super(PageExtensionAdmin, self).save_model(request, obj, form, change)
def add_structure_mode(self): if self.page and not self.page.application_urls: if page_permissions.user_can_change_page(self.request.user, page=self.page): return self.add_structure_mode_item() elif any(ph for ph in self.editable_placeholders if ph.has_change_permission(self.request.user)): return self.add_structure_mode_item() for sp in self.statics: if sp.has_change_permission(self.request): return self.add_structure_mode_item()
def add_structure_mode(self): if self.page and not self.page.application_urls: if user_can_change_page(self.request.user, page=self.page): return self.add_structure_mode_item() elif any(ph for ph in self.placeholders if ph.has_change_permission(self.request.user)): return self.add_structure_mode_item() for sp in self.statics: if sp.has_change_permission(self.request): return self.add_structure_mode_item()
def populate(self): # django CMS >= 3.6 if CMS_GTE_36 and not self.toolbar.edit_mode_active: return # django CMS <= 3.5 if not CMS_GTE_36 and not self.toolbar.edit_mode: return cms_page = get_page_draft(self.request.current_page) if not cms_page or user_can_change_page(self.request.user, cms_page): self.active_operation = self.get_active_operation() self.add_buttons()
def clean_direct_course(self): """Ensure that the user has the required permissions to change the related course page.""" course = self.cleaned_data["direct_course"] if (course and getattr(settings, "CMS_PERMISSION", False) and not page_permissions.user_can_change_page( self.request.user, # pylint: disable=no-member course.extended_object, course.extended_object.node.site, )): raise ValidationError( "You do not have permission to change this course page.") return course
def add_draft_live(self): if self.page: if self.toolbar.edit_mode_active and not self.title: self.add_page_settings_button() if user_can_change_page(self.request.user, page=self.page) and self.page.is_published(self.current_lang): return self.add_draft_live_item() elif self.placeholders: return self.add_draft_live_item() for sp in self.statics: if sp.has_change_permission(self.request): return self.add_draft_live_item()
def _setup_extension_toolbar(self): """ Does all the sanity check for the current environment: * that a page exists * permissions check on the current page It returns the page menu or None if the above conditions are not met """ page = self._get_page() if page and user_can_change_page(self.request.user, page=page): return self.toolbar.get_or_create_menu('page') return
def add_draft_live(self): if self.page: if self.toolbar.edit_mode and not self.title: self.add_page_settings_button() if user_can_change_page(self.request.user, page=self.page) and self.page.is_published(self.current_lang): return self.add_draft_live_item() elif self.placeholders: return self.add_draft_live_item() for sp in self.statics: if sp.has_change_permission(self.request): return self.add_draft_live_item()
def can_change_page(request): """ Check whether a user has the permission to change the page. This will work across all permission-related setting, with a unified interface to permission checking. """ from cms.utils import page_permissions user = request.user current_page = request.current_page if current_page: return page_permissions.user_can_change_page(user, current_page) site = Site.objects.get_current(request) return page_permissions.user_can_change_all_pages(user, site)
def populate(self): """ Adds Moderation link to Page Toolbar Menu """ # always use draft if we have a page page = get_page_draft(self.request.current_page) if page: can_change = page_permissions.user_can_change_page( self.request.user, page) else: can_change = False if not can_change: return page_menu = self.toolbar.get_menu('page') if not page_menu or page_menu.disabled: return try: extension = PageModeration.objects.get(extended_object_id=page.pk) except PageModeration.DoesNotExist: extension = None opts = PageModeration._meta url_args = [] if extension: url_name = '{}_{}_{}'.format(opts.app_label, opts.model_name, 'change') url_args.append(extension.pk) else: url_name = '{}_{}_{}'.format(opts.app_label, opts.model_name, 'add') url = get_admin_url(url_name, self.current_lang, args=url_args) if not extension: url += '?extended_object=%s' % page.pk not_edit_mode = not self.toolbar.edit_mode_active page_menu.add_modal_item(_('Moderation'), url=url, disabled=not_edit_mode)
def user_has_add_permission(self, user, **kwargs): """ Returns: True if the user has the permission to add course objects, False otherwise. A course can only be created when visiting an organization page (that will become the course's main organization) that the user has the right to update. """ if not kwargs.get("page"): return False try: organization = kwargs["page"].organization except Organization.DoesNotExist: return False return (user.has_perm("courses.add_course") and user_can_change_page(user, organization.extended_object) and super().user_has_add_permission(user, **kwargs))
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 render_page(request, page, current_language, slug): """ Renders a page """ template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context = {} context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = user_can_change_page( request.user, page) context['has_view_permissions'] = user_can_view_page(request.user, page) if not context['has_view_permissions']: return _handle_no_page(request) response = TemplateResponse(request, template_name, context) response.add_post_render_callback(set_page_cache) # Add headers for X Frame Options - this really should be changed upon moving to class based views xframe_options = page.get_xframe_options() # xframe_options can be None if there's no xframe information on the page # (eg. a top-level page which has xframe options set to "inherit") if xframe_options == Page.X_FRAME_OPTIONS_INHERIT or xframe_options is None: # This is when we defer to django's own clickjacking handling return response # We want to prevent django setting this in their middlewear response.xframe_options_exempt = True if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: # Do nothing, allowed is no header. return response elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: response['X-Frame-Options'] = 'SAMEORIGIN' elif xframe_options == Page.X_FRAME_OPTIONS_DENY: response['X-Frame-Options'] = 'DENY' return response
def clean(self): """ Permission to add a course was already checked when we displayed the list of wizard entries, but we need to prevent form hacking. """ # The current page should be an organization if not self.page: raise PermissionDenied() try: self.page.organization except Organization.DoesNotExist as error: raise PermissionDenied() from error # The user should be allowed to modify this organization page if not user_can_change_page(self.user, self.page): raise PermissionDenied() # The user should have permission to create a course object if not (self.user.is_staff and self.user.has_perm("courses.add_course")): raise PermissionDenied() return super().clean()
def render_page(request, page, current_language, slug): """ Renders a page """ template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context = {} context["lang"] = current_language context["current_page"] = page context["has_change_permissions"] = user_can_change_page(request.user, page) context["has_view_permissions"] = user_can_view_page(request.user, page) if not context["has_view_permissions"]: return _handle_no_page(request, slug) response = TemplateResponse(request, template_name, context) response.add_post_render_callback(set_page_cache) # Add headers for X Frame Options - this really should be changed upon moving to class based views xframe_options = page.get_xframe_options() # xframe_options can be None if there's no xframe information on the page # (eg. a top-level page which has xframe options set to "inherit") if xframe_options == Page.X_FRAME_OPTIONS_INHERIT or xframe_options is None: # This is when we defer to django's own clickjacking handling return response # We want to prevent django setting this in their middlewear response.xframe_options_exempt = True if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: # Do nothing, allowed is no header. return response elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: response["X-Frame-Options"] = "SAMEORIGIN" elif xframe_options == Page.X_FRAME_OPTIONS_DENY: response["X-Frame-Options"] = "DENY" return response
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return if user_can_change_page(user=self.request.user, page=self.page): try: icon_extension = HeaderBackgroundExtension.objects.get(extended_object_id=self.page.id) except HeaderBackgroundExtension.DoesNotExist: icon_extension = None try: if icon_extension: url = reverse('admin:website_headerbackgroundextension_change', args=(icon_extension.pk,)) else: url = reverse('admin:website_headerbackgroundextension_add') + '?extended_object=%s' % self.page.pk except NoReverseMatch: pass else: not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page') current_page_menu.add_modal_item("Page background", url=url, disabled=not_edit_mode)
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ response_timestamp = now() if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or (not request.toolbar.edit_mode_active and not request.toolbar.show_toolbar and not request.user.is_authenticated())): cache_content = get_page_cache(request) if cache_content is not None: content, headers, expires_datetime = cache_content response = HttpResponse(content) response._headers = headers # Recalculate the max-age header for this cached response max_age = int((expires_datetime - response_timestamp).total_seconds() + 0.5) patch_cache_control(response, max_age=max_age) return response # Get a Page model object from the request site = get_current_site() page = get_page_from_request(request, use_path=slug) toolbar = get_toolbar_from_request(request) tree_nodes = TreeNode.objects.get_for_site(site) if not page and not slug and not tree_nodes.exists(): # render the welcome page if the requested path is root "/" # and there's no pages return _render_welcome_page(request) if not page: # raise 404 _handle_no_page(request) request.current_page = page if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list(site_id=site.pk) else: user_languages = get_public_languages(site_id=site.pk) request_language = get_language_from_request(request, check_path=True) if not page.is_home and request_language not in user_languages: # The homepage is treated differently because # when a request goes to the root of the site (/) # without a language, Django will redirect to the user's # browser language which might not be a valid cms language, # this means we need to correctly redirect that request. return _handle_no_page(request) # get_published_languages will return all languages in draft mode # and published only in live mode. # These languages are then filtered out by the user allowed languages available_languages = [ language for language in user_languages if language in list(page.get_published_languages()) ] own_urls = [ request.build_absolute_uri(request.path), '/%s' % request.path, request.path, ] try: redirect_on_fallback = get_redirect_on_fallback(request_language, site_id=site.pk) except LanguageError: redirect_on_fallback = False if request_language not in user_languages: # Language is not allowed # Use the default site language default_language = get_default_language_for_site(site.pk) fallbacks = get_fallback_languages(default_language, site_id=site.pk) fallbacks = [default_language] + fallbacks else: fallbacks = get_fallback_languages(request_language, site_id=site.pk) # Only fallback to languages the user is allowed to see fallback_languages = [ language for language in fallbacks if language != request_language and language in available_languages ] language_is_unavailable = request_language not in available_languages if language_is_unavailable and not fallback_languages: # There is no page with the requested language # and there's no configured fallbacks return _handle_no_page(request) elif language_is_unavailable and (redirect_on_fallback or page.is_home): # There is no page with the requested language and # the user has explicitly requested to redirect on fallbacks, # so redirect to the first configured / available fallback language fallback = fallback_languages[0] redirect_url = page.get_absolute_url(fallback, fallback=False) else: page_path = page.get_absolute_url(request_language) page_slug = page.get_path(request_language) or page.get_slug( request_language) if slug and slug != page_slug and request.path[:len(page_path )] != page_path: # The current language does not match its slug. # Redirect to the current language. return HttpResponseRedirect(page_path) # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(request_language, fallback=False) or '' redirect_url = _clean_redirect_url(redirect_url, request_language) if redirect_url: if request.user.is_staff and toolbar.edit_mode_active: toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: # prevent redirect to self return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) structure_requested = get_cms_setting( 'CMS_TOOLBAR_URL__BUILD') in request.GET if user_can_change_page(request.user, page) and structure_requested: return render_object_structure(request, page) return render_page(request, page, current_language=request_language, slug=slug)
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 change_language_menu(self): if self.toolbar.edit_mode_active and self.page: can_change = page_permissions.user_can_change_page( user=self.request.user, page=self.page, site=self.current_site, ) else: can_change = False if can_change: language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER) if not language_menu: return None languages = get_language_dict(self.current_site.pk) remove = [(code, languages.get(code, code)) for code in self.page.get_languages() if code in languages] add = [lang for lang in languages.items() if lang not in remove] copy = [(code, name) for code, name in languages.items() if code != self.current_lang and (code, name) in remove] if add or remove or copy: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) if add: add_plugins_menu = language_menu.get_or_create_menu( '{0}-add'.format(LANGUAGE_MENU_IDENTIFIER), _('Add Translation')) if self.page.is_page_type: page_change_url = admin_reverse('cms_pagetype_change', args=(self.page.pk, )) else: page_change_url = admin_reverse('cms_page_change', args=(self.page.pk, )) for code, name in add: url = add_url_parameters(page_change_url, language=code) add_plugins_menu.add_modal_item(name, url=url) if remove: if self.page.is_page_type: translation_delete_url = admin_reverse( 'cms_pagetype_delete_translation', args=(self.page.pk, )) else: translation_delete_url = admin_reverse( 'cms_page_delete_translation', args=(self.page.pk, )) remove_plugins_menu = language_menu.get_or_create_menu( '{0}-del'.format(LANGUAGE_MENU_IDENTIFIER), _('Delete Translation')) disabled = len(remove) == 1 for code, name in remove: url = add_url_parameters(translation_delete_url, language=code) remove_plugins_menu.add_modal_item(name, url=url, disabled=disabled) if copy: copy_plugins_menu = language_menu.get_or_create_menu( '{0}-copy'.format(LANGUAGE_MENU_IDENTIFIER), _('Copy all plugins')) title = _('from %s') question = _( 'Are you sure you want to copy all plugins from %s?') if self.page.is_page_type: page_copy_url = admin_reverse('cms_pagetype_copy_language', args=(self.page.pk, )) else: page_copy_url = admin_reverse('cms_page_copy_language', args=(self.page.pk, )) for code, name in copy: copy_plugins_menu.add_ajax_item( title % name, action=page_copy_url, data={ 'source_language': code, 'target_language': self.current_lang }, question=question % name, on_success=self.toolbar.REFRESH_PAGE)
def delete_model(self, request, obj): page = obj.extended_object.page if not user_can_change_page(request.user, page): raise PermissionDenied() obj.delete()