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 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)
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
    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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
    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)
Exemplo n.º 11
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

        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)
Exemplo n.º 12
0
 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)
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
    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()
Exemplo n.º 15
0
 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
Exemplo n.º 17
0
 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)
Exemplo n.º 19
0
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
Exemplo n.º 20
0
    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()
Exemplo n.º 21
0
    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()
Exemplo n.º 22
0
    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()
Exemplo n.º 23
0
    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
Exemplo n.º 24
0
    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()
Exemplo n.º 25
0
    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 _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
Exemplo n.º 27
0
    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()
Exemplo n.º 28
0
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)
Exemplo n.º 29
0
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)
Exemplo n.º 31
0
    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))
Exemplo n.º 32
0
    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,
            )
Exemplo n.º 33
0
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
Exemplo n.º 34
0
    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()
Exemplo n.º 35
0
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
Exemplo n.º 36
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

        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)
Exemplo n.º 37
0
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)
Exemplo n.º 38
0
    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)
Exemplo n.º 39
0
    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)
Exemplo n.º 40
0
    def delete_model(self, request, obj):
        page = obj.extended_object.page

        if not user_can_change_page(request.user, page):
            raise PermissionDenied()
        obj.delete()