publik: make it possible to create publik menu from pages (#45741)

This commit is contained in:
Frédéric Péters 2020-07-27 19:09:18 +02:00
parent e28819644f
commit b7e6a7ed1e
3 changed files with 141 additions and 21 deletions

View File

@ -17,35 +17,86 @@
import json
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse
from combo.data.models import Page
def menuitem_url(request, page, subpage=None):
if subpage and subpage.redirect_url:
return subpage.get_redirect_url()
elif subpage:
return request.build_absolute_uri('/'.join(['', page.slug, subpage.slug, '']))
if page.redirect_url:
return page.get_redirect_url()
return request.build_absolute_uri('/'.join(['', page.slug, '']))
@login_required
def services_js(request, *args, **kwargs):
if not getattr(settings, 'KNOWN_SERVICES', None):
raise Http404()
services = []
portal_agent_url = None
portal_agent_title = None
for service_id, services_dict in settings.KNOWN_SERVICES.items():
for service_slug, service in services_dict.items():
if service.get('secondary') and service_id != 'authentic':
menu_items = []
if getattr(settings, 'PUBLIK_EXPLICIT_MENU', False):
pages = Page.objects.filter(
parent_id__isnull=True,
exclude_from_navigation=False)
second_level_pages = Page.objects.filter(
parent__in=pages,
exclude_from_navigation=False)
for page in pages:
if not page.is_visible(request.user, ignore_superuser=True):
continue
if service.get('is-portal-agent'):
portal_agent_url = service['url']
portal_agent_title = service['title']
services.append({
'title': service['title'],
'slug': service_slug,
'service_id': service_id,
'uniq': bool(len([x for x in services_dict.values() if not x.get('secondary')]) == 1),
'url': service['url'],
'backoffice_menu_url': service['backoffice-menu-url'],
menu_items.append(
{
'label': page.title,
'url': menuitem_url(request, page),
'slug': page.slug if page.slug != 'index' else 'home',
'icon': request.build_absolute_uri(page.picture.url) if page.picture else None,
})
for subpage in second_level_pages:
if subpage.parent_id != page.id:
continue
if not subpage.is_visible(request.user, ignore_superuser=True):
continue
menu_items.append(
{
'label': subpage.title,
'sub': True,
'url': menuitem_url(request, page, subpage),
'slug': subpage.slug,
'icon': request.build_absolute_uri(subpage.picture.url) if subpage.picture else None,
})
else:
for service_id, services_dict in settings.KNOWN_SERVICES.items():
for service_slug, service in services_dict.items():
if service.get('secondary') and service_id != 'authentic':
continue
if service.get('is-portal-agent'):
portal_agent_url = service['url']
portal_agent_title = service['title']
services.append({
'title': service['title'],
'slug': service_slug,
'service_id': service_id,
'uniq': bool(len([x for x in services_dict.values() if not x.get('secondary')]) == 1),
'url': service['url'],
'backoffice_menu_url': service['backoffice-menu-url'],
})
response_vars = {
'PUBLIK_ENVIRONMENT_LABEL': settings.TEMPLATE_VARS.get('environment_label'),
'PUBLIK_PORTAL_AGENT_URL': portal_agent_url,
'PUBLIK_PORTAL_AGENT_TITLE': portal_agent_title,
'PUBLIK_PORTAL_AGENT_EXTRA_CSS': settings.TEMPLATE_VARS.get(
'portal_agent_extra_css'),
'PUBLIK_MENU_ITEMS': menu_items,
'PUBLIK_EXPLICIT_MENU': getattr(settings, 'PUBLIK_EXPLICIT_MENU', False),
'COMBO_KNOWN_SERVICES': services,
}
response_body = '\n'.join(

View File

@ -71,14 +71,14 @@ class PostException(Exception):
pass
def element_is_visible(element, user=None):
def element_is_visible(element, user=None, ignore_superuser=False):
if element.public:
if getattr(element, 'restricted_to_unlogged', None) is True:
return (user is None or user.is_anonymous)
return True
if user is None or user.is_anonymous:
return False
if user.is_superuser:
if user.is_superuser and not ignore_superuser:
return True
page_groups = element.groups.all()
if not page_groups:
@ -404,8 +404,8 @@ class Page(models.Model):
groupnames = ', '.join([x.name for x in groups]) if groups else _('logged users')
return _('Private (%s)') % groupnames
def is_visible(self, user=None):
return element_is_visible(self, user=user)
def is_visible(self, user=None, ignore_superuser=False):
return element_is_visible(self, user=user, ignore_superuser=ignore_superuser)
def get_cells(self):
return CellBase.get_cells(page=self)

View File

@ -1,11 +1,33 @@
import json
import re
import pytest
from webtest import TestApp
from django.conf import settings
from django.contrib.auth.models import User, Group
from combo.data.models import Page
from . import test_manager
pytestmark = pytest.mark.django_db
def login(app):
test_manager.login(app, username='normal-user', password='normal-user')
@pytest.fixture
def normal_user():
try:
user = User.objects.get(username='normal-user')
user.groups = []
except User.DoesNotExist:
user = User.objects.create_user(username='normal-user', email='', password='normal-user')
return user
class KnownServices(object):
def __init__(self, known_services):
self.known_services = known_services
@ -18,18 +40,25 @@ class KnownServices(object):
settings.KNOWN_SERVICES = self.orig_value
def test_services_js_no_services(app):
def test_services_js_no_services(app, normal_user):
with KnownServices({}):
resp = app.get('/__services.js', status=404)
app.get('/__services.js', status=302)
login(app)
app.get('/__services.js', status=404)
def test_services_js_multiple_wcs(app):
def test_services_js_multiple_wcs(app, normal_user):
login(app)
resp = app.get('/__services.js', status=200)
assert resp.content_type == 'text/javascript'
assert 'var PUBLIK_ENVIRONMENT_LABEL = null' in resp.text
assert 'var PUBLIK_PORTAL_AGENT_URL = null' in resp.text
assert '"uniq": false' in resp.text
def test_services_js_portal_agent(app):
def test_services_js_portal_agent(app, normal_user):
app.get('/__services.js', status=302) # authentication required
login(app)
known_services = {
'combo': {
'portal-agent': {
@ -50,3 +79,43 @@ def test_services_js_portal_agent(app):
assert resp.content_type == 'text/javascript'
assert 'var PUBLIK_PORTAL_AGENT_URL = "http://example.net";' in resp.text
assert 'var PUBLIK_PORTAL_AGENT_TITLE = "Portal Agent"' in resp.text
def test_services_js_explicit_menu(app, normal_user, settings):
settings.PUBLIK_EXPLICIT_MENU = True
group1 = Group.objects.create(name='plop1')
group2 = Group.objects.create(name='plop2')
index_page = Page.objects.create(title='Home', slug='index',
template_name='standard', public=False,
exclude_from_navigation=False)
index_page.groups.set([group1])
other_page = Page.objects.create(title='Page', slug='page',
template_name='standard', public=False,
exclude_from_navigation=False)
other_page.groups.set([group1])
sub_page = Page.objects.create(title='Subpage', slug='subpage',
template_name='standard', parent=other_page, public=False,
exclude_from_navigation=False)
sub_page.groups.set([group2])
last_page = Page.objects.create(title='Last page', slug='lastpage',
template_name='standard', public=False,
exclude_from_navigation=False)
last_page.groups.set([group1])
def get_menu_var(resp):
return json.loads(re.findall('var PUBLIK_MENU_ITEMS = (.*);', resp.text)[0])
login(app)
resp = app.get('/__services.js', status=200)
assert [x['slug'] for x in get_menu_var(resp)] == []
normal_user.groups.set([group1])
resp = app.get('/__services.js', status=200)
assert [x['slug'] for x in get_menu_var(resp)] == ['home', 'page', 'lastpage']
assert len(get_menu_var(resp)) == 3
normal_user.groups.set([group1, group2])
resp = app.get('/__services.js', status=200)
assert [x['slug'] for x in get_menu_var(resp)] == ['home', 'page', 'subpage', 'lastpage']