api: prevent crash on invalid event_display_template (#54388)

This commit is contained in:
Valentin Deniaud 2021-05-31 17:11:27 +02:00
parent 7d7f52487c
commit 2921ed52a3
4 changed files with 56 additions and 2 deletions

View File

@ -130,6 +130,20 @@ def django_template_validator(value):
raise ValidationError(_('syntax error: %s') % e)
def event_template_validator(value):
example_event = Event(
start_datetime=now(),
publication_date=now().date(),
recurrence_end_date=now().date(),
places=1,
duration=1,
)
try:
event_text = Template(value).render(Context({'event': example_event}))
except (VariableDoesNotExist, TemplateSyntaxError) as e:
raise ValidationError(_('syntax error: %s') % e)
class ICSError(Exception):
pass
@ -224,6 +238,7 @@ class Agenda(models.Model):
_('Event display template'),
max_length=256,
blank=True,
validators=[event_template_validator],
help_text=_(
'By default event labels will be displayed to users. '
'This allows for a custom template to include additional informations. '

View File

@ -24,7 +24,7 @@ from django.db.models import Count, Prefetch, Q
from django.db.models.functions import TruncDay
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
from django.template import Context, Template
from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist
from django.urls import reverse
from django.utils.dateparse import parse_date, parse_datetime
from django.utils.encoding import force_text
@ -425,7 +425,10 @@ def get_event_detail(request, event, agenda=None, min_places=1, booked_user_exte
agenda = agenda or event.agenda
event_text = force_text(event)
if agenda.event_display_template:
event_text = Template(agenda.event_display_template).render(Context({'event': event}))
try:
event_text = Template(agenda.event_display_template).render(Context({'event': event}))
except (VariableDoesNotExist, TemplateSyntaxError):
pass
elif event.label and event.primary_event is not None:
event_text = '%s (%s)' % (
event.label,

View File

@ -119,6 +119,18 @@ def test_datetime_api_label(app):
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['text'] == 'Hello world (4/5 places remaining)'
# invalid template yields default text
invalid_templates = [
'{{ syntax error }}',
'{{ event.label|invalidfilter }}',
'{{ event.label|default:notexist }}',
]
for template in invalid_templates:
agenda.event_display_template = template
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['text'] == 'Hello world'
def test_datetime_api_urls(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)

View File

@ -579,6 +579,30 @@ def test_options_agenda_booking_check_options(app, admin_user):
app.get(url, status=404)
def test_options_agenda_event_display_template(app, admin_user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
app = login(app)
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
valid_template = '{{ event.label|default:event.slug }} - {{ event.remaining_places|add:"5" }} / {{ event.start_datetime|date }} - {{ event.agenda.name }}'
resp.form['event_display_template'] = valid_template
resp = resp.form.submit().follow()
agenda.refresh_from_db()
assert agenda.event_display_template == valid_template
invalid_templates = [
'{{ syntax error }}',
'{{ event.label|invalidfilter }}',
'{{ event.label|default:notexist }}',
]
for template in invalid_templates:
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
resp.form['event_display_template'] = template
resp = resp.form.submit()
assert 'syntax error' in resp.text
def test_options_agenda_as_manager(app, manager_user):
agenda = Agenda(label=u'Foo bar')
agenda.view_role = manager_user.groups.all()[0]