0001-api-prevent-crash-on-invalid-event_display_template-.patch
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 |
- |