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 import json
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse 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): def services_js(request, *args, **kwargs):
if not getattr(settings, 'KNOWN_SERVICES', None): if not getattr(settings, 'KNOWN_SERVICES', None):
raise Http404() raise Http404()
services = [] services = []
portal_agent_url = None portal_agent_url = None
portal_agent_title = None portal_agent_title = None
for service_id, services_dict in settings.KNOWN_SERVICES.items(): menu_items = []
for service_slug, service in services_dict.items():
if service.get('secondary') and service_id != 'authentic': 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 continue
if service.get('is-portal-agent'): menu_items.append(
portal_agent_url = service['url'] {
portal_agent_title = service['title'] 'label': page.title,
services.append({ 'url': menuitem_url(request, page),
'title': service['title'], 'slug': page.slug if page.slug != 'index' else 'home',
'slug': service_slug, 'icon': request.build_absolute_uri(page.picture.url) if page.picture else None,
'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'],
}) })
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 = { response_vars = {
'PUBLIK_ENVIRONMENT_LABEL': settings.TEMPLATE_VARS.get('environment_label'), 'PUBLIK_ENVIRONMENT_LABEL': settings.TEMPLATE_VARS.get('environment_label'),
'PUBLIK_PORTAL_AGENT_URL': portal_agent_url, 'PUBLIK_PORTAL_AGENT_URL': portal_agent_url,
'PUBLIK_PORTAL_AGENT_TITLE': portal_agent_title, 'PUBLIK_PORTAL_AGENT_TITLE': portal_agent_title,
'PUBLIK_PORTAL_AGENT_EXTRA_CSS': settings.TEMPLATE_VARS.get( 'PUBLIK_PORTAL_AGENT_EXTRA_CSS': settings.TEMPLATE_VARS.get(
'portal_agent_extra_css'), 'portal_agent_extra_css'),
'PUBLIK_MENU_ITEMS': menu_items,
'PUBLIK_EXPLICIT_MENU': getattr(settings, 'PUBLIK_EXPLICIT_MENU', False),
'COMBO_KNOWN_SERVICES': services, 'COMBO_KNOWN_SERVICES': services,
} }
response_body = '\n'.join( response_body = '\n'.join(

View File

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

View File

@ -1,11 +1,33 @@
import json
import re
import pytest import pytest
from webtest import TestApp from webtest import TestApp
from django.conf import settings 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 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): class KnownServices(object):
def __init__(self, known_services): def __init__(self, known_services):
self.known_services = known_services self.known_services = known_services
@ -18,18 +40,25 @@ class KnownServices(object):
settings.KNOWN_SERVICES = self.orig_value settings.KNOWN_SERVICES = self.orig_value
def test_services_js_no_services(app): def test_services_js_no_services(app, normal_user):
with KnownServices({}): 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) resp = app.get('/__services.js', status=200)
assert resp.content_type == 'text/javascript' assert resp.content_type == 'text/javascript'
assert 'var PUBLIK_ENVIRONMENT_LABEL = null' in resp.text assert 'var PUBLIK_ENVIRONMENT_LABEL = null' in resp.text
assert 'var PUBLIK_PORTAL_AGENT_URL = null' in resp.text assert 'var PUBLIK_PORTAL_AGENT_URL = null' in resp.text
assert '"uniq": false' 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 = { known_services = {
'combo': { 'combo': {
'portal-agent': { 'portal-agent': {
@ -50,3 +79,43 @@ def test_services_js_portal_agent(app):
assert resp.content_type == 'text/javascript' assert resp.content_type == 'text/javascript'
assert 'var PUBLIK_PORTAL_AGENT_URL = "http://example.net";' in resp.text assert 'var PUBLIK_PORTAL_AGENT_URL = "http://example.net";' in resp.text
assert 'var PUBLIK_PORTAL_AGENT_TITLE = "Portal Agent"' 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']