general: refine navigation/menu page visibility (#28963)

This commit is contained in:
Frédéric Péters 2018-12-13 11:16:31 +01:00
parent 7c944f8382
commit f3f7202c21
5 changed files with 69 additions and 7 deletions

View File

@ -17,9 +17,10 @@
from django.template.loader import get_template
from combo.data.models import Page
from combo.utils import NothingInCacheException
def render_menu(context, level=0, root_page=None, depth=1):
def render_menu(context, level=0, root_page=None, depth=1, ignore_visibility=False):
context['root_page'] = root_page
if root_page:
level = len(root_page.get_parents_and_self())
@ -27,7 +28,7 @@ def render_menu(context, level=0, root_page=None, depth=1):
template = get_template('combo/menu.html')
return template.render(context)
def get_menu_context(context, level=0, current_page=None, depth=1):
def get_menu_context(context, level=0, current_page=None, depth=1, ignore_visibility=False):
if 'hierarchical_pages_by_id' not in context:
context['hierarchical_pages_by_id'] = Page.get_with_hierarchy_attributes()
pages_by_id = context['hierarchical_pages_by_id']
@ -68,7 +69,11 @@ def get_menu_context(context, level=0, current_page=None, depth=1):
for element in elements:
if element.exclude_from_navigation:
continue
if not context.get('render_skeleton'):
if not ignore_visibility:
if context.get('render_skeleton'):
if not element.public:
# mark the menu cell for asynchronous rendering.
raise NothingInCacheException()
if not element.is_visible(context['request'].user):
continue
menuitem = {'page': element}

View File

@ -15,7 +15,7 @@
{% if check_badges %}data-check-badges="true"{% endif %}
data-api-root="{{ site_base }}/api/">
<div id="title"><h1>{{ page.title }}</h1></div>
<div id="menu">{% block menu %}{% show_menu %}{% endblock %}</div>
<div id="menu">{% block menu %}{% show_menu ignore_visibility=True %}{% endblock %}</div>
<div id="content">
{% block messages %}

View File

@ -148,7 +148,7 @@ class ExtraPlaceholderNode(template.Node):
return skeleton_text(context, self.placeholder_name, content=self.content)
@register.inclusion_tag('combo/menu.html', takes_context=True)
def show_menu(context, level=0, current_page=None, depth=1, reduce_depth=False):
def show_menu(context, level=0, current_page=None, depth=1, ignore_visibility=False, reduce_depth=False):
if reduce_depth:
depth -= 1
new_context = {
@ -156,7 +156,7 @@ def show_menu(context, level=0, current_page=None, depth=1, reduce_depth=False):
'render_skeleton': context.get('render_skeleton'),
'request': context['request']}
return get_menu_context(new_context, level=level, current_page=current_page,
depth=depth)
depth=depth, ignore_visibility=ignore_visibility)
@register.simple_tag(takes_context=True)
def page_absolute_url(context, page):

View File

@ -4,7 +4,7 @@ import os
import pytest
import requests
from combo.data.models import Page, CellBase, TextCell, LinkCell, JsonCellBase, JsonCell, ConfigJsonCell
from combo.data.models import Page, CellBase, TextCell, LinkCell, MenuCell, JsonCellBase, JsonCell, ConfigJsonCell
from django.conf import settings
from django.db import connection
from django.forms.widgets import Media
@ -109,6 +109,41 @@ def test_link_cell():
assert cell.render(ctx).strip() == '<a href="http://example.net/#anchor">altertitle</a>'
def test_menu_cell():
Page.objects.all().delete()
parent = page = Page(title='Page1', slug='page1', template_name='standard')
page.save()
page = Page(title='Page2', slug='page2', template_name='standard',
parent=parent)
page.save()
page = Page(title='Page3', slug='page3', template_name='standard',
parent=parent, public=False)
page.save()
cell = MenuCell(root_page=parent, order=0, page=parent)
cell.save()
request = RequestFactory().get('/page1/')
request.user = None
ctx = {'page': parent, 'request': request}
assert 'menu-page2' in cell.render(ctx)
assert 'menu-page3' not in cell.render(ctx)
request.user = User(username='foo', email='foo@example.net')
assert 'menu-page2' in cell.render(ctx)
assert 'menu-page3' in cell.render(ctx)
# check cell is deferred in skeletons if some pages are private
ctx = {'page': parent, 'request': request, 'render_skeleton': True}
with pytest.raises(NothingInCacheException):
cell.render(ctx)
# and that it's rendered directly if all pages are public
page.public = True
page.save()
ctx = {'page': parent, 'request': request, 'render_skeleton': True}
assert 'menu-page2' in cell.render(ctx)
assert 'menu-page3' in cell.render(ctx)
def test_variant_templates():
page = Page(title='example page', slug='example-page')
page.save()

View File

@ -268,6 +268,13 @@ def test_page_skeleton(app):
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/foo/bar'))
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/badredir'))
# add a page with restricted visibility
page = Page(title='RestrictedVisibility', slug='restrictedvisibilit',
template_name='standard', public=False)
page.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert 'RestrictedVisibility' in resp.text
def test_subpage_location(app):
Page.objects.all().delete()
@ -316,6 +323,21 @@ def test_subpage_location(app):
resp = app.get('/second/child-second/grand-child-second/', status=200)
assert 'Grand child of second' in resp.text
def test_menu(app):
Page.objects.all().delete()
page = Page(title='Page1', slug='index', template_name='standard')
page.save()
page = Page(title='Page2', slug='page2', template_name='standard')
page.save()
page = Page(title='Page3', slug='page3', template_name='standard', public=False)
page.save()
resp = app.get('/', status=200)
assert 'menu-index' in resp.text
assert 'menu-page2' in resp.text
assert 'menu-page3' in resp.text
def test_404(app):
Page.objects.all().delete()
resp = app.get('/foobar/', status=404)