From 6cbb7c94d2a6414fbbf85afaa84c208430f3af56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 9 Nov 2020 09:22:35 +0100
Subject: [PATCH] api: proper error if datetime part is wrong in a slot
 (#48132)

---
 chrono/api/views.py |  9 ++++++++-
 tests/test_api.py   | 18 +++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/chrono/api/views.py b/chrono/api/views.py
index 4889eac..a4f8600 100644
--- a/chrono/api/views.py
+++ b/chrono/api/views.py
@@ -832,7 +832,14 @@ class Fillslots(APIView):
                         err_class='all slots must have the same meeting type id (%s)' % meeting_type_id,
                         http_status=status.HTTP_400_BAD_REQUEST,
                     )
-                datetimes.add(make_aware(datetime.datetime.strptime(datetime_str, '%Y-%m-%d-%H%M')))
+                try:
+                    datetimes.add(make_aware(datetime.datetime.strptime(datetime_str, '%Y-%m-%d-%H%M')))
+                except ValueError:
+                    raise APIError(
+                        _('bad datetime format: %s') % datetime_str,
+                        err_class='bad datetime format: %s' % datetime_str,
+                        http_status=status.HTTP_400_BAD_REQUEST,
+                    )
 
             try:
                 resources = get_resources_from_request(request, agenda)
diff --git a/tests/test_api.py b/tests/test_api.py
index 48a7ede..274df98 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1426,26 +1426,38 @@ def test_booking_api_meeting_fillslots(app, meetings_agenda, user):
     assert resp_cancel.json['err'] == 0
     assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 2
 
+
+def test_booking_api_meeting_fillslots_wrong_slot(app, user):
+    agenda = Agenda.objects.create(label='Foo', kind='meetings')
+    app.authorization = ('Basic', ('john.doe', 'password'))
+
     impossible_slots = ['1:2017-05-22-1130', '2:2017-05-22-1100']
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda_id, params={'slots': impossible_slots}, status=400)
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': impossible_slots}, status=400)
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'all slots must have the same meeting type id (1)'  # legacy
     assert resp.json['err_class'] == 'all slots must have the same meeting type id (1)'
     assert resp.json['err_desc'] == 'all slots must have the same meeting type id (1)'
 
     unknown_slots = ['0:2017-05-22-1130']
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda_id, params={'slots': unknown_slots}, status=400)
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': unknown_slots}, status=400)
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'invalid meeting type id: 0'  # legacy
     assert resp.json['err_class'] == 'invalid meeting type id: 0'
     assert resp.json['err_desc'] == 'invalid meeting type id: 0'
     unknown_slots = ['foobar:2017-05-22-1130']
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda_id, params={'slots': unknown_slots}, status=400)
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': unknown_slots}, status=400)
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'invalid meeting type id: foobar'  # legacy
     assert resp.json['err_class'] == 'invalid meeting type id: foobar'
     assert resp.json['err_desc'] == 'invalid meeting type id: foobar'
 
+    badformat_slots = ['foo:2020-10-28-14h00']
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': badformat_slots}, status=400)
+    assert resp.json['err'] == 1
+    assert resp.json['reason'] == 'bad datetime format: 2020-10-28-14h00'  # legacy
+    assert resp.json['err_class'] == 'bad datetime format: 2020-10-28-14h00'
+    assert resp.json['err_desc'] == 'bad datetime format: 2020-10-28-14h00'
+
 
 def test_booking_api_meeting_across_daylight_saving_time(app, meetings_agenda, user):
     meetings_agenda.maximal_booking_delay = 365
-- 
2.28.0

