From f1be1dfac65a2ac3694bfce6aeaa88f2344a1a0c Mon Sep 17 00:00:00 2001 From: Thibault Coudray Date: Thu, 25 Jul 2024 11:18:52 +0200 Subject: [PATCH] (PC-31032)[API] fix: add `cascade` param in `externalUrls` and `permissions` Without it, DELETE on `/venueProviders/{venue.id}` was returning a 500 --- api/src/pcapi/core/providers/models.py | 4 +- api/src/pcapi/routes/pro/venue_providers.py | 7 ++- .../routes/pro/delete_venue_provider_test.py | 53 +++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 api/tests/routes/pro/delete_venue_provider_test.py diff --git a/api/src/pcapi/core/providers/models.py b/api/src/pcapi/core/providers/models.py index 131769fcff2..db49c940a30 100644 --- a/api/src/pcapi/core/providers/models.py +++ b/api/src/pcapi/core/providers/models.py @@ -193,11 +193,11 @@ class VenueProvider(PcObject, Base, Model, DeactivableMixin): # external URLs externalUrls: sa_orm.Mapped["VenueProviderExternalUrls"] = sa_orm.relationship( - "VenueProviderExternalUrls", uselist=False, back_populates="venueProvider" + "VenueProviderExternalUrls", uselist=False, back_populates="venueProvider", cascade="all,delete" ) # permissions permissions: sa_orm.Mapped["VenueProviderPermission"] = sa_orm.relationship( - "VenueProviderPermission", uselist=True, back_populates="venueProvider" + "VenueProviderPermission", uselist=True, back_populates="venueProvider", cascade="all,delete" ) # This column is unused by our code but by the data team diff --git a/api/src/pcapi/routes/pro/venue_providers.py b/api/src/pcapi/routes/pro/venue_providers.py index 4be2e167c0f..459dc5041cb 100644 --- a/api/src/pcapi/routes/pro/venue_providers.py +++ b/api/src/pcapi/routes/pro/venue_providers.py @@ -1,5 +1,6 @@ from flask_login import current_user from flask_login import login_required +from sqlalchemy.orm import exc as orm_exc from werkzeug.exceptions import NotFound import pcapi.core.offerers.models as offerers_models @@ -128,9 +129,11 @@ def update_venue_provider(body: PostVenueProviderBody) -> VenueProviderResponse: @login_required @spectree_serialize(on_success_status=204, api=blueprint.pro_private_schema) def delete_venue_provider(venue_provider_id: int) -> None: - venue_provider = repository.get_venue_provider_by_id(venue_provider_id) - if not venue_provider: + try: + venue_provider = repository.get_venue_provider_by_id(venue_provider_id) + except orm_exc.NoResultFound: raise NotFound() + rest.check_user_has_access_to_offerer(current_user, venue_provider.venue.managingOffererId) api.delete_venue_provider(venue_provider, author=current_user) diff --git a/api/tests/routes/pro/delete_venue_provider_test.py b/api/tests/routes/pro/delete_venue_provider_test.py new file mode 100644 index 00000000000..fbabb7de34a --- /dev/null +++ b/api/tests/routes/pro/delete_venue_provider_test.py @@ -0,0 +1,53 @@ +import pytest + +import pcapi.core.offerers.factories as offerers_factories +from pcapi.core.providers import api as providers_api +from pcapi.core.providers import repository as providers_repository +import pcapi.core.providers.factories as providers_factories + + +@pytest.mark.usefixtures("db_session") +def test_delete_venue_provider(client): + # Given + user_offerer = offerers_factories.UserOffererFactory() + venue = offerers_factories.VenueFactory(managingOfferer=user_offerer.offerer) + provider = providers_factories.PublicApiProviderFactory() + venue_provider = providers_factories.VenueProviderFactory(venue=venue, provider=provider) + + # VenueProvider sub tables + providers_repository.add_all_permissions_for_venue_provider(venue_provider=venue_provider) + providers_api.update_venue_provider_external_urls(venue_provider, notification_external_url="https://notify.com") + + # When + response = client.with_session_auth(email=user_offerer.user.email).delete(f"/venueProviders/{venue_provider.id}") + + # Then + assert response.status_code == 204 + + +@pytest.mark.usefixtures("db_session") +def test_delete_venue_provider_should_return_404(client): + # Given + user_offerer = offerers_factories.UserOffererFactory() + offerers_factories.VenueFactory(managingOfferer=user_offerer.offerer) + + # When + response = client.with_session_auth(email=user_offerer.user.email).delete("/venueProviders/12345") + + # Then + assert response.status_code == 404 + + +@pytest.mark.usefixtures("db_session") +def test_delete_venue_provider_should_return_403(client): + # Given + user_offerer = offerers_factories.UserOffererFactory() + venue = offerers_factories.VenueFactory() + provider = providers_factories.PublicApiProviderFactory() + venue_provider = providers_factories.VenueProviderFactory(venue=venue, provider=provider) + + # When + response = client.with_session_auth(email=user_offerer.user.email).delete(f"/venueProviders/{venue_provider.id}") + + # Then + assert response.status_code == 403