api: check shared custody in multiple agendas fillslots (#62598)

This commit is contained in:
Valentin Deniaud 2022-03-08 15:38:22 +01:00
parent 5674a606ff
commit 6311c5146a
3 changed files with 95 additions and 2 deletions

View File

@ -264,6 +264,10 @@ class AgendaOrSubscribedSlugsSerializer(AgendaOrSubscribedSlugsMixin, serializer
pass
class MultipleAgendasFillslotsSerializer(AgendaOrSubscribedSlugsSerializer):
guardian_external_id = serializers.CharField(max_length=250, required=False)
class RecurringFillslotsQueryStringSerializer(AgendaOrSubscribedSlugsSerializer):
action = serializers.ChoiceField(required=True, choices=['update', 'book', 'unbook'])

View File

@ -1887,7 +1887,7 @@ class MultipleAgendasEventsFillslots(EventsFillslots):
multiple_agendas = True
def post(self, request):
serializer = serializers.AgendaOrSubscribedSlugsSerializer(
serializer = serializers.MultipleAgendasFillslotsSerializer(
data=request.query_params, context={'user_external_id': request.data.get('user_external_id')}
)
if not serializer.is_valid():
@ -1896,6 +1896,7 @@ class MultipleAgendasEventsFillslots(EventsFillslots):
self.agendas = data['agendas']
self.agenda_slugs = data['agenda_slugs']
self.guardian_external_id = data.get('guardian_external_id')
return self.fillslots(request)
@ -1926,6 +1927,17 @@ class MultipleAgendasEventsFillslots(EventsFillslots):
'%s@%s' % (event.agenda.slug, event.slug) for event in events_outside_subscriptions
)
raise APIErrorBadRequest(N_('Some events are outside user subscriptions: %s'), event_slugs)
if self.guardian_external_id:
events_outside_custody = events.exclude(
pk__in=Agenda.filter_for_guardian(
events, self.guardian_external_id, payload['user_external_id']
).values('pk')
)
if events_outside_custody.exists():
event_slugs = ', '.join(
'%s@%s' % (event.agenda.slug, event.slug) for event in events_outside_custody
)
raise APIErrorBadRequest(N_('Some events are outside guardian custody: %s'), event_slugs)
return events

View File

@ -5,7 +5,7 @@ from unittest import mock
import pytest
from django.db import connection
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import localtime, now
from django.utils.timezone import localtime, make_aware, now
from chrono.agendas.models import (
Agenda,
@ -15,7 +15,10 @@ from chrono.agendas.models import (
Desk,
Event,
MeetingType,
Person,
Resource,
SharedCustodyAgenda,
SharedCustodyRule,
Subscription,
TimePeriod,
VirtualMember,
@ -4350,3 +4353,77 @@ def test_fillslot_recurring_event_booking_forbidden(app, user):
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug))
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'event is recurrent'
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week
def test_api_events_fillslots_multiple_agendas_shared_custody(app, user):
agenda = Agenda.objects.create(label='First agenda', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
Event.objects.create(
slug='event-wednesday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=9, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Event.objects.create(
slug='event-thursday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=10, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Subscription.objects.create(
agenda=agenda,
user_external_id='child_id',
date_start=now(),
date_end=now() + datetime.timedelta(days=14),
)
father = Person.objects.create(user_external_id='father_id', name='John Doe')
mother = Person.objects.create(user_external_id='mother_id', name='Jane Doe')
child = Person.objects.create(user_external_id='child_id', name='James Doe')
agenda = SharedCustodyAgenda.objects.create(first_guardian=father, second_guardian=mother)
agenda.children.add(child)
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=[0, 1, 2])
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=[3, 4, 5, 6])
app.authorization = ('Basic', ('john.doe', 'password'))
params = {'user_external_id': 'child_id', 'slots': 'first-agenda@event-wednesday'}
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id', params=params
)
assert resp.json['booking_count'] == 1
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-wednesday'
params['slots'] = 'first-agenda@event-thursday'
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id', params=params
)
assert resp.json['booking_count'] == 1
# unknown guardian
Booking.objects.all().delete()
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=unknown_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday'
# unknown child
child.delete()
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday'