Projet

Général

Profil

0001-api-prevent-crash-on-invalid-event_display_template-.patch

Valentin Deniaud, 01 juin 2021 14:42

Télécharger (5,31 ko)

Voir les différences:

Subject: [PATCH] api: prevent crash on invalid event_display_template (#54388)

 chrono/agendas/models.py  | 15 +++++++++++++++
 chrono/api/views.py       |  7 +++++--
 tests/manager/test_all.py | 24 ++++++++++++++++++++++++
 tests/test_api.py         | 12 ++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)
chrono/agendas/models.py
130 130
        raise ValidationError(_('syntax error: %s') % e)
131 131

  
132 132

  
133
def event_template_validator(value):
134
    example_event = Event(
135
        start_datetime=now(),
136
        publication_date=now().date(),
137
        recurrence_end_date=now().date(),
138
        places=1,
139
        duration=1,
140
    )
141
    try:
142
        event_text = Template(value).render(Context({'event': example_event}))
143
    except (VariableDoesNotExist, TemplateSyntaxError) as e:
144
        raise ValidationError(_('syntax error: %s') % e)
145

  
146

  
133 147
class ICSError(Exception):
134 148
    pass
135 149

  
......
221 235
        _('Event display template'),
222 236
        max_length=256,
223 237
        blank=True,
238
        validators=[event_template_validator],
224 239
        help_text=_(
225 240
            'By default event labels will be displayed to users. This allows for a custom template to include additional informations. For example, "{{ event.label }} - {{ event.start_datetime }}" will show event datetime after label. Available variables: event.label (label), event.start_datetime (start date/time), event.places (places), event.remaining_places (remaining places), event.duration (duration), event.pricing (pricing).'
226 241
        ),
chrono/api/views.py
24 24
from django.db.models.functions import TruncDay
25 25
from django.http import Http404, HttpResponse
26 26
from django.shortcuts import get_object_or_404
27
from django.template import Context, Template
27
from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist
28 28
from django.urls import reverse
29 29
from django.utils.dateparse import parse_date, parse_datetime
30 30
from django.utils.encoding import force_text
......
417 417
    agenda = agenda or event.agenda
418 418
    event_text = force_text(event)
419 419
    if agenda.event_display_template:
420
        event_text = Template(agenda.event_display_template).render(Context({'event': event}))
420
        try:
421
            event_text = Template(agenda.event_display_template).render(Context({'event': event}))
422
        except (VariableDoesNotExist, TemplateSyntaxError):
423
            pass
421 424
    elif event.label and event.primary_event is not None:
422 425
        event_text = '%s (%s)' % (
423 426
            event.label,
tests/manager/test_all.py
571 571
    app.get(url, status=404)
572 572

  
573 573

  
574
def test_options_agenda_event_display_template(app, admin_user):
575
    agenda = Agenda.objects.create(label='Foo bar', kind='events')
576

  
577
    app = login(app)
578
    resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
579
    valid_template = '{{ event.label|default:event.slug }} - {{ event.remaining_places|add:"5" }} / {{ event.start_datetime|date }} - {{ event.agenda.name }}'
580
    resp.form['event_display_template'] = valid_template
581
    resp = resp.form.submit().follow()
582

  
583
    agenda.refresh_from_db()
584
    assert agenda.event_display_template == valid_template
585

  
586
    invalid_templates = [
587
        '{{ syntax error }}',
588
        '{{ event.label|invalidfilter }}',
589
        '{{ event.label|default:notexist }}',
590
    ]
591
    for template in invalid_templates:
592
        resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
593
        resp.form['event_display_template'] = template
594
        resp = resp.form.submit()
595
        assert 'syntax error' in resp.text
596

  
597

  
574 598
def test_options_agenda_as_manager(app, manager_user):
575 599
    agenda = Agenda(label=u'Foo bar')
576 600
    agenda.view_role = manager_user.groups.all()[0]
tests/test_api.py
566 566
    resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
567 567
    assert resp.json['data'][0]['text'] == 'Hello world (4/5 places remaining)'
568 568

  
569
    # invalid template yields default text
570
    invalid_templates = [
571
        '{{ syntax error }}',
572
        '{{ event.label|invalidfilter }}',
573
        '{{ event.label|default:notexist }}',
574
    ]
575
    for template in invalid_templates:
576
        agenda.event_display_template = template
577
        agenda.save()
578
        resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
579
        assert resp.json['data'][0]['text'] == 'Hello world'
580

  
569 581

  
570 582
def test_datetime_api_urls(app):
571 583
    agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
572
-