def test_returns_404_if_api_key_cant_access_venue(mock_synchronize_stocks,
                                                  app):
    offerer = offers_factories.OffererFactory(siren=123456789)
    offers_factories.VenueFactory(managingOfferer=offerer, id=3)

    offerer2 = offers_factories.OffererFactory(siren=123456780)
    ApiKeyFactory(offerer=offerer2)

    mock_synchronize_stocks.return_value = {}

    test_client = TestClient(app.test_client())
    test_client.auth_header = {
        "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}"
    }

    response1 = test_client.post(
        "/v2/venue/3/stocks",
        json={"stocks": [{
            "ref": "123456789",
            "available": 4
        }]})
    response2 = test_client.post(
        "/v2/venue/123/stocks",
        json={"stocks": [{
            "ref": "123456789",
            "available": 4
        }]})

    assert response1.status_code == 404
    assert response2.status_code == 404
    mock_synchronize_stocks.assert_not_called()
Пример #2
0
    def test_should_returns_204_with_cancellation_allowed(self, client):
        # Given
        stock = offers_factories.EventStockFactory(
            offer__name="Chouette concert")
        booking = bookings_factories.IndividualBookingFactory(stock=stock)
        ApiKeyFactory(offerer=booking.offerer)

        # When
        response = client.patch(
            f"/v2/bookings/cancel/token/{booking.token}",
            headers={"Authorization": "Bearer " + DEFAULT_CLEAR_API_KEY},
        )

        # Then
        # cancellation can trigger more than one request to Batch
        assert len(push_testing.requests) >= 1
        assert response.status_code == 204
        updated_booking = Booking.query.one()
        assert updated_booking.isCancelled
        assert updated_booking.status is BookingStatus.CANCELLED

        assert push_testing.requests[-1] == {
            "group_id": "Cancel_booking",
            "message": {
                "body":
                """Ta réservation "Chouette concert" a été annulée par l'offreur.""",
                "title": "Réservation annulée",
            },
            "user_ids": [booking.individualBooking.userId],
        }
def test_accepts_request_with_price(price, expected_price, app):
    ProviderFactory(name="Pass Culture API Stocks", localClass="PCAPIStocks")
    offerer = offers_factories.OffererFactory(siren=123456789)
    venue = offers_factories.VenueFactory(managingOfferer=offerer)
    offer_to_update = offers_factories.OfferFactory(
        product__idAtProviders="123456789",
        product__subcategoryId="LIVRE_PAPIER",
        idAtProviders=f"123456789@{venue.id}",
        product__extraData={"prix_livre": expected_price},
        venue=venue,
    )
    ApiKeyFactory(offerer=offerer)

    test_client = TestClient(app.test_client())
    test_client.auth_header = {
        "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}"
    }

    response = test_client.post(f"/v2/venue/{venue.id}/stocks",
                                json={
                                    "stocks": [{
                                        "ref": "123456789",
                                        "available": 4,
                                        "price": price
                                    }]
                                })

    assert response.status_code == 204
    assert offer_to_update.stocks[0].price == expected_price
def test_delete_api_key_not_allowed(client):
    user_offerer = UserOffererFactory()
    api_key = ApiKeyFactory()

    client.with_session_auth(user_offerer.user.email)
    response = client.delete(f"/offerers/api_keys/{api_key.prefix}")

    assert response.status_code == 403
Пример #5
0
def create_industrial_pro_users_api_keys(offerers_by_name):
    """Create api_keys with shape : {env}_{offererId}_clearSecret{offererId} ex: 'testing_12_clearSecret12'"""
    logger.info("create_industrial_pro_users_api_keys")

    for offerer in offerers_by_name.items():
        ApiKeyFactory(
            offerer=offerer[1], prefix=f"{settings.ENV}_{offerer[1].id}", hash_secret=f"clearSecret{offerer[1].id}"
        )

    logger.info("created %d offerers with api key", len(offerers_by_name))
Пример #6
0
    def test_when_api_key_is_provided_and_rights_and_regular_offer(self, client):
        # Given
        booking = bookings_factories.IndividualBookingFactory()
        ApiKeyFactory(offerer=booking.offerer, prefix="test_prefix")

        # When
        url = f"/v2/bookings/token/{booking.token}"
        response = client.get(url, headers={"Authorization": "Bearer test_prefix_clearSecret"})

        # Then
        assert response.status_code == 200
def test_maximal_api_key_reached(client):
    user_offerer = UserOffererFactory()
    for i in range(5):
        ApiKeyFactory(prefix=f"prefix_{i}", offerer=user_offerer.offerer)

    client.with_session_auth(user_offerer.user.email)
    response = client.post(f"/offerers/{humanize(user_offerer.offerer.id)}/api_keys")

    assert response.status_code == 400
    assert response.json["api_key_count_max"] == "Le nombre de clés maximal a été atteint"
    assert ApiKey.query.count() == 5
Пример #8
0
    def test_should_returns_204_with_lowercase_token(self, client):
        # Given
        booking = bookings_factories.IndividualBookingFactory()
        ApiKeyFactory(offerer=booking.offerer)

        # When
        response = client.patch(
            f"/v2/bookings/cancel/token/{booking.token.lower()}",
            headers={"Authorization": "Bearer " + DEFAULT_CLEAR_API_KEY},
        )

        assert response.status_code == 204
        booking = Booking.query.one()
        assert booking.isCancelled
        assert booking.status is BookingStatus.CANCELLED
Пример #9
0
    def test_when_given_api_key_not_related_to_booking_offerer(self, client):
        # Given
        booking = bookings_factories.IndividualBookingFactory()
        ApiKeyFactory()  # another offerer's API key

        # When
        auth = "Bearer development_prefix_clearSecret"
        url = f"/v2/bookings/token/{booking.token}"
        response = client.get(url, headers={"Authorization": auth})

        # Then
        assert response.status_code == 403
        assert response.json["user"] == [
            "Vous n’avez pas les droits suffisants pour valider cette contremarque car cette réservation n'a pas été faite sur une de vos offres, ou que votre rattachement à la structure est encore en cours de validation"
        ]
Пример #10
0
    def when_the_api_key_is_not_linked_to_the_right_offerer(self, client):
        # Given
        booking = bookings_factories.BookingFactory()
        ApiKeyFactory()  # another offerer's API key

        # When
        response = client.patch(
            f"/v2/bookings/cancel/token/{booking.token}",
            headers={"Authorization": "Bearer " + DEFAULT_CLEAR_API_KEY},
        )

        # Then
        assert response.status_code == 403
        assert response.json["user"] == [
            "Vous n'avez pas les droits suffisants pour annuler cette réservation."
        ]
        def test_when_the_api_key_is_not_linked_to_the_right_offerer(
                self, client):
            # Given
            booking = bookings_factories.BookingFactory()
            ApiKeyFactory()  # another offerer's API key

            # When
            wrong_auth = f"Bearer {DEFAULT_CLEAR_API_KEY}"
            url = f"/v2/bookings/keep/token/{booking.token}"
            response = client.patch(url, headers={"Authorization": wrong_auth})

            # Then
            assert response.status_code == 403
            assert response.json["user"] == [
                "Vous n’avez pas les droits suffisants pour valider cette contremarque car cette réservation n'a pas été faite sur une de vos offres, ou que votre rattachement à la structure est encore en cours de validation"
            ]
def test_returns_comprehensive_errors(mock_synchronize_stocks, app):
    ApiKeyFactory()

    mock_synchronize_stocks.return_value = {}

    test_client = TestClient(app.test_client())
    test_client.auth_header = {
        "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}"
    }

    response1 = test_client.post("/v2/venue/3/stocks", json={})
    response2 = test_client.post(
        "/v2/venue/3/stocks",
        json={
            "stocks": [
                {
                    "ref": "123456789"
                },
                {
                    "wrong_key": "123456789"
                },
                {
                    "ref": "1234567890",
                    "available": "abc"
                },
                {
                    "ref": "12345678901",
                    "available": -3
                },
            ]
        },
    )

    assert response1.status_code == 400
    assert response1.json["stocks"] == ["Ce champ est obligatoire"]
    assert response2.status_code == 400
    assert response2.json["stocks.0.available"] == ["Ce champ est obligatoire"]
    assert response2.json["stocks.1.available"] == ["Ce champ est obligatoire"]
    assert response2.json["stocks.1.ref"] == ["Ce champ est obligatoire"]
    assert response2.json["stocks.2.available"] == [
        "Saisissez un nombre valide"
    ]
    assert response2.json["stocks.3.available"] == [
        "Saisissez un nombre supérieur ou égal à 0"
    ]
    mock_synchronize_stocks.assert_not_called()
        def test_when_api_key_is_provided_and_rights_and_regular_offer(
                self, client):
            booking = bookings_factories.BookingFactory(token="ABCDEF")
            ApiKeyFactory(offerer=booking.offerer)

            url = f"/v2/bookings/use/token/{booking.token}"
            response = client.patch(
                url,
                headers={
                    "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}",
                },
            )

            assert response.status_code == 204
            booking = Booking.query.one()
            assert booking.isUsed
            assert booking.status == BookingStatus.USED
        def test_when_api_key_provided_is_related_to_regular_offer_with_rights(
                self, client):
            booking = bookings_factories.UsedIndividualBookingFactory()
            ApiKeyFactory(offerer=booking.offerer)

            url = f"/v2/bookings/keep/token/{booking.token}"
            response = client.patch(
                url,
                headers={
                    "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}",
                },
            )

            assert response.status_code == 204
            booking = Booking.query.one()
            assert not booking.isUsed
            assert booking.status is not BookingStatus.USED
            assert booking.dateUsed is None
def test_generate_and_save_api_key_for_offerer():
    # Given
    siren_unknown = "291893841948"
    offerer_1_having_api_key = offers_factories.OffererFactory()
    ApiKeyFactory(offerer=offerer_1_having_api_key)

    offerer_2_needing_api_key = offers_factories.OffererFactory()

    # When
    generate_and_save_api_key_for_offerer([
        siren_unknown, offerer_1_having_api_key.siren,
        offerer_2_needing_api_key.siren
    ])

    # Then
    assert ApiKey.query.count() == 2
    offerers = {k.offerer for k in ApiKey.query.all()}
    assert offerers == {offerer_1_having_api_key, offerer_2_needing_api_key}
        def test_when_api_key_is_provided_and_booking_has_been_cancelled_already(
                self, client):
            # Given
            booking = bookings_factories.CancelledBookingFactory()
            ApiKeyFactory(offerer=booking.offerer)

            # When
            url = f"/v2/bookings/use/token/{booking.token}"
            auth = "Bearer development_prefix_clearSecret"
            response = client.patch(url, headers={"Authorization": auth})

            # Then
            assert response.status_code == 403
            assert response.json["booking"] == [
                "Cette réservation a été annulée"
            ]
            booking = Booking.query.get(booking.id)
            assert not booking.isUsed
            assert booking.status is not BookingStatus.USED
        def test_when_api_key_is_provided_and_booking_has_been_cancelled_already(
                self, client):
            # Given
            booking = bookings_factories.CancelledBookingFactory()
            ApiKeyFactory(offerer=booking.offerer)

            # When
            url = f"/v2/bookings/keep/token/{booking.token}"
            auth = f"Bearer {DEFAULT_CLEAR_API_KEY}"
            response = client.patch(url, headers={"Authorization": auth})

            # Then
            booking = Booking.query.get(booking.id)
            assert response.status_code == 403
            assert response.json["booking"] == [
                "Cette réservation a été annulée"
            ]
            assert not booking.isUsed
            assert booking.status is BookingStatus.CANCELLED
def test_accepts_request(app):
    ProviderFactory(name="Pass Culture API Stocks", localClass="PCAPIStocks")
    offerer = offers_factories.OffererFactory(siren=123456789)
    venue = offers_factories.VenueFactory(managingOfferer=offerer, id=3)
    offer_to_update = offers_factories.OfferFactory(
        product__idAtProviders="123456789",
        product__subcategoryId="LIVRE_PAPIER",
        idAtProviders=f"123456789@{venue.id}",
        venue=venue,
    )
    ApiKeyFactory(offerer=offerer)

    test_client = TestClient(app.test_client())
    test_client.auth_header = {
        "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}"
    }

    response = test_client.post(
        f"/v2/venue/{venue.id}/stocks",
        json={
            "stocks": [
                {
                    "ref": "123456789",
                    "available": 4,
                    "price": 30
                },
                {
                    "ref": "1234567890",
                    "available": 0,
                    "price": 10
                },
            ]
        },
    )

    assert response.status_code == 204
    assert len(offer_to_update.stocks) == 1
    assert offer_to_update.stocks[0].quantity == 4
    assert offer_to_update.stocks[0].price == 30
Пример #19
0
    def test_when_user_has_rights_on_offerer(self, app):
        pro = users_factories.ProFactory()
        offerer = offers_factories.OffererFactory()
        offers_factories.UserOffererFactory(user=pro, offerer=offerer)
        venue_1 = offers_factories.VenueFactory(
            managingOfferer=offerer,
            withdrawalDetails="Venue withdrawal details")
        offers_factories.OfferFactory(venue=venue_1)
        venue_2 = offers_factories.VenueFactory(
            managingOfferer=offerer,
            withdrawalDetails="Other venue withdrawal details")
        offers_factories.VenueFactory(
            managingOfferer=offerer,
            withdrawalDetails="More venue withdrawal details")
        ApiKeyFactory(offerer=offerer, prefix="testenv_prefix")
        ApiKeyFactory(offerer=offerer, prefix="testenv_prefix2")
        offers_factories.BankInformationFactory(venue=venue_1,
                                                applicationId=2,
                                                status="REJECTED")
        offers_factories.BankInformationFactory(venue=venue_1, applicationId=3)
        offers_factories.BankInformationFactory(venue=venue_2, applicationId=4)

        client = TestClient(app.test_client()).with_session_auth(pro.email)
        n_queries = (
            testing.AUTHENTICATION_QUERIES +
            1  # check_user_has_access_to_offerer
            + 1  # Offerer api_key prefix
            + 1  # Offerer hasDigitalVenueAtLeastOneOffer
            + 1  # Offerer BankInformation
            + 1  # Offerer hasMissingBankInformation
        )
        with testing.assert_num_queries(n_queries):
            response = client.get(f"/offerers/{humanize(offerer.id)}")

        expected_serialized_offerer = {
            "address":
            offerer.address,
            "apiKey": {
                "maxAllowed": 5,
                "prefixes": ["testenv_prefix", "testenv_prefix2"]
            },
            "bic":
            None,
            "iban":
            None,
            "city":
            offerer.city,
            "dateCreated":
            format_into_utc_date(offerer.dateCreated),
            "dateModifiedAtLastProvider":
            format_into_utc_date(offerer.dateModifiedAtLastProvider),
            "demarchesSimplifieesApplicationId":
            None,
            "hasDigitalVenueAtLeastOneOffer":
            False,
            "fieldsUpdated":
            offerer.fieldsUpdated,
            "hasMissingBankInformation":
            True,
            "id":
            humanize(offerer.id),
            "idAtProviders":
            offerer.idAtProviders,
            "isValidated":
            offerer.isValidated,
            "lastProviderId":
            offerer.lastProviderId,
            "managedVenues": [{
                "audioDisabilityCompliant":
                False,
                "address":
                offererVenue.address,
                "bookingEmail":
                offererVenue.bookingEmail,
                "city":
                offererVenue.city,
                "comment":
                offererVenue.comment,
                "departementCode":
                offererVenue.departementCode,
                "id":
                humanize(offererVenue.id),
                "isValidated":
                offererVenue.isValidated,
                "isVirtual":
                offererVenue.isVirtual,
                "managingOffererId":
                humanize(offererVenue.managingOffererId),
                "mentalDisabilityCompliant":
                False,
                "motorDisabilityCompliant":
                False,
                "name":
                offererVenue.name,
                "postalCode":
                offererVenue.postalCode,
                "publicName":
                offererVenue.publicName,
                "venueLabelId":
                humanize(offererVenue.venueLabelId),
                "venueTypeId":
                humanize(offererVenue.venueTypeId),
                "visualDisabilityCompliant":
                False,
                "withdrawalDetails":
                offererVenue.withdrawalDetails,
            } for offererVenue in offerer.managedVenues],
            "name":
            offerer.name,
            "postalCode":
            offerer.postalCode,
            "siren":
            offerer.siren,
        }
        assert response.status_code == 200
        assert response.json == expected_serialized_offerer
Пример #20
0
    def test_authenticated_with_api_key_but_token_not_found(self, client):
        ApiKeyFactory(prefix="test_prefix")
        response = client.get("/v2/bookings/token/12345", headers={"Authorization": "Bearer test_prefix_clearSecret"})

        assert response.status_code == 404
        assert response.json["global"] == ["Cette contremarque n'a pas été trouvée"]