Example #1
0
    def view_revision(self, request, **kwargs):
        # render a page for a popup in an old revision
        revision_pk = kwargs.pop('revision_pk')
        language = request.GET.get('language')
        page_version = PageVersion.objects.get(id=revision_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_view_page(user, page_version.draft):
            messages.error(request, _('Missing permission to view this page.'))
            prev = request.META.get('HTTP_REFERER')
            if prev:
                return redirect(prev)
            else:
                raise Http404

        page_absolute_url = page_version.hidden_page.get_draft_url(
            language=language)

        context = SekizaiContext({
            'render_page': page_version.hidden_page,
            'page_version': page_version,
            'is_popup': False,
            'request': request,
            'page_absolute_url': page_absolute_url
        })

        return render(request, self.view_revision_template, context=context)
Example #2
0
    def add_logout_button(self, parent):
        # If current page is not published or has view restrictions user is redirected to the home page:
        # * published page: no redirect
        # * unpublished page: redirect to the home page
        # * published page with login_required: redirect to the home page
        # * published page with view permissions: redirect to the home page
        page_is_published = self.page and self.page.is_published(
            self.current_lang)

        if page_is_published and not self.page.login_required:
            anon_can_access = page_permissions.user_can_view_page(
                user=AnonymousUser(),
                page=self.page,
                site=self.current_site,
            )
        else:
            anon_can_access = False

        on_success = self.toolbar.REFRESH_PAGE if anon_can_access else '/'

        # We'll show "Logout Joe Bloggs" if the name fields in auth.User are completed, else "Logout jbloggs". If
        # anything goes wrong, it'll just be "Logout".

        user_name = self.get_username()
        logout_menu_text = _('Logout %s') % user_name if user_name else _(
            'Logout')

        parent.add_ajax_item(
            logout_menu_text,
            action=admin_reverse('logout'),
            active=True,
            on_success=on_success,
            method='GET',
        )
Example #3
0
    def add_logout_button(self, parent):
        # If current page is not published or has view restrictions user is redirected to the home page:
        # * published page: no redirect
        # * unpublished page: redirect to the home page
        # * published page with login_required: redirect to the home page
        # * published page with view permissions: redirect to the home page

        if (self.page and self.page.is_published(self.current_lang) and not self.page.login_required and
                page_permissions.user_can_view_page(AnonymousUser(), page=self.page)):
            on_success = self.toolbar.REFRESH_PAGE
        else:
            on_success = '/'

        # We'll show "Logout Joe Bloggs" if the name fields in auth.User are completed, else "Logout jbloggs". If
        # anything goes wrong, it'll just be "Logout".

        user_name = self.get_username()
        logout_menu_text = _('Logout %s') % user_name if user_name else _('Logout')

        parent.add_ajax_item(
            logout_menu_text,
            action=admin_reverse('logout'),
            active=True,
            on_success=on_success,
            method='GET',
        )
Example #4
0
 def inner(request, *args, **kwargs):
     page = request.current_page
     if page:
         if page.login_required and not request.user.is_authenticated():
             return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL)
         if not user_can_view_page(request.user, page):
             return _handle_no_page(request, "$")
     return func(request, *args, **kwargs)
Example #5
0
 def inner(request, *args, **kwargs):
     page = request.current_page
     if page:
         if page.login_required and not request.user.is_authenticated():
             return redirect_to_login(urlquote(request.get_full_path()),
                                      settings.LOGIN_URL)
         if not user_can_view_page(request.user, page):
             return _handle_no_page(request)
     return func(request, *args, **kwargs)
Example #6
0
    def test_visibility_after_move_page(self):
        superuser = self.get_superuser()
        user1 = self._create_user("user1", is_staff=True, is_superuser=False)

        visible = create_page("visible",
                              "nav_playground.html",
                              "en",
                              published=True)
        visible_child = create_page("visible_child",
                                    "nav_playground.html",
                                    "en",
                                    parent=visible,
                                    published=True)
        invisible_for_user1 = create_page("invisible",
                                          "nav_playground.html",
                                          "en",
                                          published=True)

        assign_user_to_page(visible,
                            user1,
                            grant_on=ACCESS_PAGE_AND_DESCENDANTS,
                            can_view=True)
        assign_user_to_page(invisible_for_user1,
                            superuser,
                            grant_on=ACCESS_PAGE_AND_DESCENDANTS,
                            can_view=True)

        with self.login_user_context(user1):
            response = self.client.get(
                visible_child.get_public_object().get_absolute_url())
            self.assertEqual(response.status_code, 200)

            response = self.client.get(
                invisible_for_user1.get_public_object().get_absolute_url())
            self.assertEqual(response.status_code, 404)

        with self.login_user_context(superuser):
            move_url = self.get_admin_url(Page, 'move_page', visible_child.pk)
            response = self.client.post(
                move_url, {
                    'id': visible_child.pk,
                    'position': 0,
                    'target': invisible_for_user1.pk,
                })
            self.assertEqual(response.status_code, 200)
            visible_child = visible_child.reload()
            self.assertEqual(visible_child.parent_page.pk,
                             invisible_for_user1.pk)

        # Ignore cached_func
        User = get_user_model()
        user1 = User.objects.get(pk=user1.pk)
        self.assertFalse(user_can_view_page(user=user1, page=visible_child))
def check_if_page_is_visible(request, page):
    user = request.user
    if page.publisher_is_draft:
        return False

    if page.login_required and not user.is_authenticated():
        return False

    page_is_visible = user_can_view_page(user, page)

    if page_is_visible:
        # Let the cms handle publication dates
        page_is_visible = Page.objects.published().filter(pk=page.pk).exists()
    return page_is_visible
Example #8
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
Example #9
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
Example #10
0
 def assertViewNotAllowed(self, page, user=None):
     if not user:
         user = AnonymousUser()
     self.assertFalse(user_can_view_page(user, page))
 def assertViewAllowed(self, page, user):
     self.assertTrue(user_can_view_page(user, page))
Example #12
0
 def assertViewNotAllowed(self, page, user):
     self.assertFalse(user_can_view_page(user, page))
Example #13
0
 def assertViewAllowed(self, page, user):
     self.assertTrue(user_can_view_page(user, page))
 def assertViewNotAllowed(self, page, user):
     self.assertFalse(user_can_view_page(user, page))
Example #15
0
    def diff_view(self, request, **kwargs):
        # view that shows a revision on the left and one on the right
        # if the right revision has value zero: the current page is used!
        # -> page id is only necessary in the utter case
        # if the comparison_pk is zero: the latest version is used
        # comparison_pk and base_pk are primary keys for *pages*!

        # also called left_pk
        left_pk = kwargs.pop('left_pk')
        # also called right_pk
        right_pk = kwargs.pop('right_pk')
        page_pk = kwargs.pop('page_pk')

        right_page_is_active_page = True

        language = request.GET.get('language')

        left = 'page'
        right = 'page'

        # get the draft we are talking about
        page_draft = get_object_or_404(Page, pk=page_pk).get_draft_object()

        # check if the current user may view the revision
        # -> if the user may see the page
        user = get_current_user()
        if not user_can_view_page(user, page_draft):
            messages.error(request, _('Missing permission to view this page.'))
            prev = request.META.get('HTTP_REFERER')
            if prev:
                return redirect(prev)
            else:
                raise Http404

        # the right panel has id=0
        # -> use the draft of the page
        # -> else: fetch the page
        if int(right_pk) == 0:
            right_page = page_draft
            right_page_is_active_page = True
        else:
            right = 'pageVersion'
            right_page = PageVersion.objects.get(pk=right_pk)
            right_page_is_active_page = False

        # the left panel has id=0
        # -> use the latest PageVersion draft of the page
        # -> else: fetch the page
        if int(left_pk) == 0:
            page_draft_versions = PageVersion.objects.filter(draft=page_draft, active=True, language=language)\
                .order_by('-hidden_page__changed_date')[:1]

            if page_draft_versions.count() > 0:
                left_page = page_draft_versions.first()
                left = 'pageVersion'
            else:
                messages.info(request,
                              _(u'There are no snapshots for this page'))
                return self.render_close_frame()
        else:
            left = 'pageVersion'
            left_page = PageVersion.objects.get(pk=left_pk)

        # list of page's revisions to show as the left sidebar
        revision_list = PageVersion.objects.filter(draft=page_draft,
                                                   language=language)
        # group the revisions by date
        grouped_revisions = {}
        for rev in revision_list.iterator():
            key = rev.hidden_page.changed_date.strftime("%Y-%m-%d")
            if key not in grouped_revisions.keys():
                grouped_revisions[key] = []
            grouped_revisions[key].insert(0, rev)
        sorted_grouped_revisions = sorted(grouped_revisions.items(),
                                          key=lambda i: i[0],
                                          reverse=True)

        # differences between the placeholders
        if left == 'pageVersion':
            l_page = left_page.hidden_page
        else:
            l_page = left_page
        if right == 'pageVersion':
            r_page = right_page.hidden_page
        else:
            r_page = right_page

        diffs = create_placeholder_contents(l_page, r_page, request, language)

        left_page_absolute_url = left_page.hidden_page.get_draft_url(
            language=language)

        context = SekizaiContext({
            'left':
            left,
            'right':
            right,
            'left_page':
            left_page,
            'right_page':
            right_page,
            'is_popup':
            True,
            'page':
            page_draft.pk,
            'active_left_page_version_pk':
            left_page.pk,
            'request':
            request,
            'sorted_grouped_revisions':
            sorted_grouped_revisions,
            'active_language':
            language,
            'all_languages':
            page_draft.languages.split(','),
            'diffs':
            diffs,
            'left_page_absolute_url':
            left_page_absolute_url,
            'right_page_is_active_page':
            right_page_is_active_page
        })

        return render(request,
                      self.diff_view_template,
                      context=context.flatten())
Example #16
0
 def assertViewNotAllowed(self, page, user=None):
     if not user:
         user = AnonymousUser()
     self.assertFalse(user_can_view_page(user, page))
Example #17
0
def get_public_page_with_fallbacks(page, request):
    """
    the plugin should show the published page whenever it exists or the draft page otherwise.

    On a public content, the draft page should not be shown at all but this is left to the
    caller.

    This is inspired by what DjangoCMS does in its main view:
    https://github.com/django-cms/django-cms/blob/3.8.0/cms/views.py#L37
    """
    page = page.get_public_object()
    request_language = translation.get_language_from_request(request,
                                                             check_path=True)

    if not page:
        return None

    # Check permissions
    site = get_current_site()
    if not page_permissions.user_can_view_page(request.user, page, site):
        return None

    if request.user.is_staff:
        user_languages = i18n.get_language_list(site_id=site.pk)
    else:
        user_languages = i18n.get_public_languages(site_id=site.pk)

    # 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())
    ]

    if request_language not in user_languages:
        # Language is not allowed
        # Use the default site language
        default_language = i18n.get_default_language_for_site(site.pk)
        fallbacks = i18n.get_fallback_languages(default_language,
                                                site_id=site.pk)
        fallbacks = [default_language] + fallbacks
    else:
        fallbacks = i18n.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
    ]

    if request_language not in available_languages:
        if not fallback_languages:
            # There is no page with the requested language
            # and there's no configured fallbacks
            return None
        if request_language in page.get_languages():
            # The page was already published and later unpublished in the current
            # language. In this case we must not fallback to another language.
            return None

    return page
Example #18
0
def get_relevant_page_with_fallbacks(context, instance):
    """
    The plugin should show the published page whenever it exists or the draft page
    otherwise but only in edit mode.

    This is inspired by what DjangoCMS does in its main view:
    https://github.com/django-cms/django-cms/blob/3.8.0/cms/views.py#L37
    """
    request = context["request"]
    site = get_current_site()

    # Check permissions
    if not page_permissions.user_can_view_page(request.user, instance.page,
                                               site):
        return None

    relevant_page = instance.page.get_public_object()

    if not relevant_page:
        if context.get(
                "current_page") and context["current_page"].publisher_is_draft:
            return instance.page
        return None

    if request.user.is_staff:
        user_languages = i18n.get_language_list(site_id=site.pk)
    else:
        user_languages = i18n.get_public_languages(site_id=site.pk)

    # These languages are then filtered out by the user allowed languages
    available_languages = [
        language for language in user_languages
        if language in list(relevant_page.get_published_languages())
    ]

    request_language = translation.get_language_from_request(request,
                                                             check_path=True)
    if request_language not in user_languages:
        # Language is not allowed
        # Use the default site language
        default_language = i18n.get_default_language_for_site(site.pk)
        fallbacks = i18n.get_fallback_languages(default_language,
                                                site_id=site.pk)
        fallbacks = [default_language] + fallbacks
    else:
        fallbacks = i18n.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
    ]

    if request_language not in available_languages:
        if not fallback_languages:
            # There is no page with the requested language
            # and there's no configured fallbacks
            return None
        if request_language in relevant_page.get_languages():
            # The page was already published and later unpublished in the current
            # language. In this case we must not fallback to another language.
            return None

    return relevant_page