generated from bisco/codex-bootstrap
fix: allow public reservation posts without csrf
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.cache import cache
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APIClient, APITestCase
|
||||||
|
|
||||||
from bookings.models import Reservation
|
from bookings.models import Reservation
|
||||||
from bookings.services import generate_confirmation_token
|
from bookings.services import generate_confirmation_token
|
||||||
@@ -16,6 +18,7 @@ from shows.models import Performance, Show, Venue
|
|||||||
|
|
||||||
class BookingApiTests(APITestCase):
|
class BookingApiTests(APITestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
cache.clear()
|
||||||
self.show = Show.objects.create(
|
self.show = Show.objects.create(
|
||||||
title="Open Stage",
|
title="Open Stage",
|
||||||
slug="open-stage-api",
|
slug="open-stage-api",
|
||||||
@@ -90,6 +93,48 @@ class BookingApiTests(APITestCase):
|
|||||||
mail.outbox[0].body,
|
mail.outbox[0].body,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@override_settings(SITE_BASE_URL="https://tickets.azionelab.example")
|
||||||
|
def test_reservation_creation_allows_anonymous_post_without_csrf(self):
|
||||||
|
csrf_client = APIClient(enforce_csrf_checks=True)
|
||||||
|
|
||||||
|
with self.captureOnCommitCallbacks(execute=True):
|
||||||
|
response = csrf_client.post(
|
||||||
|
reverse("api-reservation-create", kwargs={"performance_id": self.performance.id}),
|
||||||
|
{
|
||||||
|
"name": "Maria Rossi",
|
||||||
|
"email": "maria@example.com",
|
||||||
|
"party_size": 2,
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
|
self.assertEqual(response.data["status"], Reservation.Status.PENDING)
|
||||||
|
|
||||||
|
@override_settings(SITE_BASE_URL="https://tickets.azionelab.example")
|
||||||
|
def test_reservation_creation_ignores_session_csrf_for_public_endpoint(self):
|
||||||
|
csrf_client = APIClient(enforce_csrf_checks=True)
|
||||||
|
user = get_user_model().objects.create_user(
|
||||||
|
username="box-office",
|
||||||
|
email="staff@example.com",
|
||||||
|
password="test-pass-123",
|
||||||
|
)
|
||||||
|
csrf_client.force_login(user)
|
||||||
|
|
||||||
|
with self.captureOnCommitCallbacks(execute=True):
|
||||||
|
response = csrf_client.post(
|
||||||
|
reverse("api-reservation-create", kwargs={"performance_id": self.performance.id}),
|
||||||
|
{
|
||||||
|
"name": "Maria Rossi",
|
||||||
|
"email": "maria@example.com",
|
||||||
|
"party_size": 2,
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
|
self.assertEqual(response.data["status"], Reservation.Status.PENDING)
|
||||||
|
|
||||||
def test_reservation_creation_schedules_email_after_commit(self):
|
def test_reservation_creation_schedules_email_after_commit(self):
|
||||||
with self.captureOnCommitCallbacks(execute=False) as callbacks:
|
with self.captureOnCommitCallbacks(execute=False) as callbacks:
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import api_view, throttle_classes
|
from rest_framework.decorators import api_view, authentication_classes, permission_classes, throttle_classes
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.throttling import AnonRateThrottle
|
from rest_framework.throttling import AnonRateThrottle
|
||||||
|
|
||||||
@@ -35,6 +36,8 @@ class ReservationConfirmThrottle(AnonRateThrottle):
|
|||||||
|
|
||||||
|
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
|
@authentication_classes([])
|
||||||
|
@permission_classes([AllowAny])
|
||||||
@throttle_classes([ReservationCreateThrottle])
|
@throttle_classes([ReservationCreateThrottle])
|
||||||
def create_reservation(request, performance_id):
|
def create_reservation(request, performance_id):
|
||||||
get_object_or_404(Performance, pk=performance_id, show__is_published=True)
|
get_object_or_404(Performance, pk=performance_id, show__is_published=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user