Projet

Général

Profil

0001-manager-allow-templated-ICS-URL-66323.patch

Valentin Deniaud, 27 juin 2022 15:21

Télécharger (5,86 ko)

Voir les différences:

Subject: [PATCH] manager: allow templated ICS URL (#66323)

 chrono/agendas/models.py        |  7 ++++---
 chrono/manager/forms.py         | 19 +++++++++++++++++-
 tests/manager/test_exception.py | 35 +++++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 4 deletions(-)
chrono/agendas/models.py
2422 2422

  
2423 2423
    def _check_ics_content(self):
2424 2424
        if self.ics_url:
2425
            ics_url = Template(self.ics_url).render(Context(settings.TEMPLATE_VARS))
2425 2426
            try:
2426
                response = requests.get(self.ics_url, proxies=settings.REQUESTS_PROXIES)
2427
                response = requests.get(ics_url, proxies=settings.REQUESTS_PROXIES)
2427 2428
                response.raise_for_status()
2428 2429
            except requests.HTTPError as e:
2429 2430
                raise ICSError(
2430 2431
                    _('Failed to retrieve remote calendar (%(url)s, HTTP error %(status_code)s).')
2431
                    % {'url': self.ics_url, 'status_code': e.response.status_code}
2432
                    % {'url': ics_url, 'status_code': e.response.status_code}
2432 2433
                )
2433 2434
            except requests.RequestException as e:
2434 2435
                raise ICSError(
2435 2436
                    _('Failed to retrieve remote calendar (%(url)s, %(exception)s).')
2436
                    % {'url': self.ics_url, 'exception': e}
2437
                    % {'url': ics_url, 'exception': e}
2437 2438
                )
2438 2439
            try:
2439 2440
                # override response encoding received in HTTP headers as it may
chrono/manager/forms.py
28 28
from django.conf import settings
29 29
from django.contrib.auth.models import Group
30 30
from django.core.exceptions import FieldDoesNotExist
31
from django.core.validators import URLValidator
31 32
from django.db import transaction
32 33
from django.db.models import DurationField, ExpressionWrapper, F
33 34
from django.forms import ValidationError, formset_factory
35
from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist
34 36
from django.utils.encoding import force_text
35 37
from django.utils.formats import date_format
36 38
from django.utils.timezone import localtime, make_aware, now
......
1195 1197
        required=False,
1196 1198
        help_text=_('ICS file containing events which will be considered as exceptions.'),
1197 1199
    )
1198
    ics_url = forms.URLField(
1200
    ics_url = forms.CharField(
1199 1201
        label=_('URL'),
1202
        max_length=200,
1200 1203
        required=False,
1201 1204
        help_text=_('URL to remote calendar which will be synchronised hourly.'),
1202 1205
    )
......
1206 1209
        if not cleaned_data.get('ics_file') and not cleaned_data.get('ics_url'):
1207 1210
            raise forms.ValidationError(_('Please provide an ICS File or an URL.'))
1208 1211

  
1212
    def clean_ics_url(self):
1213
        url = self.cleaned_data['ics_url']
1214
        if not url:
1215
            return url
1216

  
1217
        try:
1218
            url = Template(url).render(Context(settings.TEMPLATE_VARS))
1219
        except (TemplateSyntaxError, VariableDoesNotExist) as e:
1220
            raise ValidationError(_('syntax error: %s') % e)
1221

  
1222
        URLValidator()(url)
1223

  
1224
        return self.cleaned_data['ics_url']
1225

  
1209 1226

  
1210 1227
class DeskExceptionsImportForm(ExceptionsImportForm):
1211 1228
    all_desks = forms.BooleanField(label=_('Apply exceptions on all desks of the agenda'), required=False)
tests/manager/test_exception.py
772 772
    assert 'Failed to retrieve remote calendar (https://example.com/foo.ics, SSL error).' in resp.text
773 773

  
774 774

  
775
@override_settings(TEMPLATE_VARS={'passerelle_url': 'https://passerelle.publik.love/'})
776
@mock.patch('chrono.agendas.models.requests.get')
777
def test_agenda_import_time_period_exception_with_remote_ics_templated_url(mocked_get, app, admin_user):
778
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
779
    desk = Desk.objects.create(agenda=agenda, label='New Desk')
780
    login(app)
781

  
782
    resp = app.get('/manage/agendas/desk/%s/import-exceptions-from-ics/' % desk.pk)
783
    resp.form['ics_url'] = '{{ passerelle_url }}holidays/test/holidays.ics'
784
    mocked_response = mock.Mock()
785
    mocked_response.text = """BEGIN:VCALENDAR
786
VERSION:2.0
787
PRODID:-//foo.bar//EN
788
BEGIN:VEVENT
789
DTSTART:20180101
790
DTEND:20180101
791
SUMMARY:New Year's Eve
792
END:VEVENT
793
END:VCALENDAR"""
794
    mocked_get.return_value = mocked_response
795
    resp = resp.form.submit(status=302)
796
    assert TimePeriodException.objects.filter(desk=desk).count() == 1
797
    assert TimePeriodExceptionSource.objects.filter(desk=desk).count() == 1
798
    assert mocked_get.call_args.args[0] == 'https://passerelle.publik.love/holidays/test/holidays.ics'
799

  
800
    resp = app.get('/manage/agendas/desk/%s/import-exceptions-from-ics/' % desk.pk)
801
    resp.form['ics_url'] = '{{ unknown }}holidays/test/holidays.ics'
802
    resp = resp.form.submit(status=200)
803
    assert 'Enter a valid URL.' in resp.text
804

  
805
    resp.form['ics_url'] = '{{ { }}holidays/test/holidays.ics'
806
    resp = resp.form.submit(status=200)
807
    assert 'syntax error' in resp.text
808

  
809

  
775 810
@mock.patch('chrono.agendas.models.requests.get')
776 811
def test_agenda_import_time_period_exception_url_desk_all_desks(mocked_get, app, admin_user):
777 812
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
778
-