def when_the_logged_user_has_not_rights_on_offerer(self, app): # Given pro_user = create_user(email="*****@*****.**", public_name="Mr Books") offerer = create_offerer(siren="793875030") user_offerer = create_user_offerer(pro_user, offerer) venue = create_venue(offerer) book_offer = create_offer_with_event_product(venue) stock = create_stock(offer=book_offer) user = users_factories.UserFactory() booking = create_booking(user=user, stock=stock, venue=venue) repository.save(booking, user_offerer) offerer_with_api_key = create_offerer() repository.save(offerer_with_api_key) api_key = random_token(64) offerer_api_key = create_api_key_for_offerer( offerer_with_api_key, api_key) repository.save(offerer_api_key) # When response = (TestClient(app.test_client()).with_auth( user.email).patch("/v2/bookings/cancel/token/{}".format( booking.token))) # Then assert response.status_code == 403 assert response.json["global"] == [ "Vous n'avez pas les droits d'accès suffisant pour accéder à cette information." ]
def test_should_returns_204_with_lowercase_token(self, app): # Given pro_user = create_user(email="Mr [email protected]", public_name="Mr Books") offerer = create_offerer(siren="793875030") user_offerer = create_user_offerer(pro_user, offerer) venue = create_venue(offerer) book_offer = create_offer_with_event_product(venue) stock = create_stock(offer=book_offer) user = users_factories.UserFactory() booking = create_booking(user=user, stock=stock, venue=venue) repository.save(booking, user_offerer) api_key = random_token(64) offerer_api_key = create_api_key_for_offerer(offerer, api_key) repository.save(offerer_api_key) # When token = booking.token.lower() response = TestClient(app.test_client()).patch( "/v2/bookings/cancel/token/{}".format(token), headers={ "Authorization": "Bearer " + api_key, "Origin": "http://localhost" }, ) # Then assert response.status_code == 204 updated_booking = Booking.query.first() assert updated_booking.isCancelled
def test_cancel_a_booking_already_cancelled(self, app): # Given pro_user = create_user(email="Mr [email protected]", public_name="Mr Books") offerer = create_offerer(siren="793875030") user_offerer = create_user_offerer(pro_user, offerer) venue = create_venue(offerer) book_offer = create_offer_with_thing_product(venue) stock = create_stock(offer=book_offer) user = users_factories.UserFactory() booking = create_booking(user=user, stock=stock, is_cancelled=True, venue=venue) repository.save(booking, user_offerer) api_key = random_token(64) offerer_api_key = create_api_key_for_offerer(offerer, api_key) repository.save(offerer_api_key) # When response = TestClient(app.test_client()).patch( "/v2/bookings/cancel/token/{}".format(booking.token), headers={ "Authorization": "Bearer " + api_key, "Origin": "http://localhost" }, ) # Then assert response.status_code == 410 assert response.json["global"] == [ "Cette contremarque a déjà été annulée" ]
def test_legacy_api_key(self): offerer = offers_factories.OffererFactory() value = random_token(64) ApiKey(value=value, offerer=offerer) found_api_key = offerers_api.find_api_key(value) assert found_api_key.offerer == offerer
def test_correct_technical_parameters(self, build_qr_code): api.generate_qr_code(random_token()) build_qr_code.assert_called_once_with( version=2, error_correction=3, box_size=5, border=1, )
def test_ignores_empty_lines(self, mocked_create_activated_user_offerer): # given create_activated_user_offerer.return_value = UserOfferer() csv_reader = [ ["nom", "prénom", "email"], [], ["Mortimer", "Philip", "*****@*****.**" % random_token()], [""], ["Mortimer", "Philip", "*****@*****.**" % random_token()], ] # when user_offerers = iterate_rows_for_user_offerers(csv_reader) # then assert len(user_offerers) == 2
def create_booking( user: User, amount: Optional[Union[Decimal, float]] = None, date_created: datetime = datetime.utcnow(), date_used: datetime = None, idx: int = None, is_cancelled: bool = False, is_used: bool = False, quantity: int = 1, stock: Stock = None, token: str = None, venue: VenueSQLEntity = None, ) -> Booking: booking = Booking() offerer = create_offerer(siren="987654321", address="Test address", city="Test city", postal_code="93000", name="Test name") if venue is None: venue = create_venue( offerer=offerer, name="Test offerer", booking_email="*****@*****.**", address="123 rue test", postal_code="93000", city="Test city", departement_code="93", ) if stock is None: price = amount if amount is not None else 10 product_with_thing_type = create_offer_with_thing_product(venue) stock = create_stock_with_thing_offer(offerer=offerer, venue=venue, offer=product_with_thing_type, price=price) if not stock.offer: stock.offer = create_offer_with_thing_product(venue) booking.user = user booking.amount = amount if amount is not None else stock.price booking.dateCreated = date_created booking.dateUsed = date_used booking.id = idx booking.isCancelled = is_cancelled booking.isUsed = is_used booking.quantity = quantity booking.stock = stock booking.token = token if token is not None else random_token() booking.userId = user.id booking.confirmationDate = bookings_api.compute_confirmation_date( stock.beginningDatetime, date_created) return booking
def test_save_api_key_create_relation_offerer_api_key(app): # given( offerer = create_offerer() repository.save(offerer) offererApiKey = ApiKey() offererApiKey.value = random_token(64) offererApiKey.offererId = offerer.id # when repository.save(offererApiKey) # then assert offerer.apiKey.value == offererApiKey.value
def test_save_api_key_raise_api_error_when_offerer_does_not_exist(app): # given offererApiKey = ApiKey() offererApiKey.value = random_token(64) offererApiKey.offererId = 65675 # when with pytest.raises(ApiErrors) as error: repository.save(offererApiKey) # then assert error.value.errors["offererId"] == [ "Aucun objet ne correspond à cet identifiant dans notre base de données" ]
def test_raises_exception_when_api_key_is_provided_but_related_offerer_does_not_have_rights_on_booking( self, app): # Given validApiKey = ApiKey() validApiKey.prefix = random_token(64) validApiKey.offererId = 67 # When with pytest.raises(ApiErrors) as errors: check_api_key_allows_to_validate_booking(validApiKey, None) # Then assert errors.value.errors["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_raises_exception_when_api_key_is_provided_but_related_offerer_does_not_have_rights_on_booking( self, app): # Given validApiKey = ApiKey() validApiKey.value = random_token(64) validApiKey.offererId = 67 # When with pytest.raises(ApiErrors) as errors: check_api_key_allows_to_validate_booking(validApiKey, None) # Then assert errors.value.errors["user"] == [ "Vous n'avez pas les droits suffisants pour valider cette contremarque." ]
def test_reset_password_fail_for_password_strength(app): reset_token = random_token() user = users_factories.UserFactory( resetPasswordToken=reset_token, resetPasswordTokenValidityLimit=(datetime.utcnow() + timedelta(hours=1)), ) old_password = user.password new_password = "******" data = {"reset_password_token": reset_token, "new_password": new_password} response = TestClient(app.test_client()).post("/native/v1/reset_password", json=data) user = find_user_by_id(user.id) assert response.status_code == 400 assert user.password == old_password
def test_does_not_raise_error_when_api_key_is_provided_and_is_related_to_offerer_id( self, app): # Given user = create_user() offerer = create_offerer() user_offerer = create_user_offerer(user, offerer, None) repository.save(user, offerer, user_offerer) validApiKey = ApiKey() validApiKey.value = random_token(64) validApiKey.offererId = offerer.id repository.save(validApiKey) # The the following should not raise check_api_key_allows_to_validate_booking(validApiKey, offerer.id)
def test_should_prevent_a_used_booking_from_being_cancelled( self, app): # Given pro_user = create_user(email="Mr [email protected]", public_name="Mr Books") offerer = create_offerer(siren="793875030") user_offerer = create_user_offerer(pro_user, offerer) venue = create_venue(offerer) book_offer = create_offer_with_event_product(venue) stock = create_stock(offer=book_offer) user = create_user(email="*****@*****.**", public_name="J.F") create_deposit(user) booking = create_booking(user=user, stock=stock, is_used=True, venue=venue) repository.save(booking, user_offerer) api_key = random_token(64) offerer_api_key = create_api_key_for_offerer(offerer, api_key) repository.save(offerer_api_key) # When response = TestClient(app.test_client()).patch( "/v2/bookings/cancel/token/{}".format(booking.token), headers={ "Authorization": "Bearer " + api_key, "Origin": "http://localhost" }, ) # Then assert response.status_code == 403 assert response.json["global"] == [ "Impossible d'annuler une réservation consommée" ] updated_booking = Booking.query.first() assert updated_booking.isUsed assert updated_booking.isCancelled is False
def create_booking_for_event( # pylint: disable=redefined-builtin amount: int = 50, date_created: datetime = datetime.utcnow(), is_cancelled: bool = False, quantity: int = 1, type: EventType = EventType.CINEMA, user: User = None, ) -> Booking: product = Product(from_dict={"type": str(type)}) offer = Offer() stock = Stock() booking = Booking(from_dict={"amount": amount}) offer.product = product stock.offer = offer booking.stock = stock booking.quantity = quantity booking.user = user booking.isCancelled = is_cancelled booking.token = random_token() booking.dateCreated = date_created return booking
def create_booking_for_user_on_specific_stock_bypassing_capping_limits( user_id: int, stock_id: int) -> None: stock = Stock.query.get(stock_id) user = User.query.get(user_id) quantity = 1 validation.check_offer_already_booked(user, stock.offer) validation.check_quantity(stock.offer, quantity) validation.check_can_book_free_offer(user, stock) validation.check_stock_is_bookable(stock) booking = models.Booking() # FIXME: this is not right. PcObject's constructor should allow # `Booking(stock=stock, ...)` booking.userId = user.id booking.stockId = stock.id booking.amount = stock.price booking.quantity = quantity booking.token = random_token() repository.save(booking) redis.add_offer_id(client=app.redis_client, offer_id=stock.offerId)
def when_the_api_key_is_not_linked_to_the_right_offerer(self, app): # Given pro_user = create_user(email="Mr [email protected]", public_name="Mr Books") offerer = create_offerer(siren="793875030") user_offerer = create_user_offerer(pro_user, offerer) venue = create_venue(offerer) book_offer = create_offer_with_event_product(venue) stock = create_stock(offer=book_offer) user = create_user(email="*****@*****.**", public_name="J.F") create_deposit(user) booking = create_booking(user=user, stock=stock, venue=venue) repository.save(booking, user_offerer) offerer_with_api_key = create_offerer() repository.save(offerer_with_api_key) api_key = random_token(64) offerer_api_key = create_api_key_for_offerer( offerer_with_api_key, api_key) repository.save(offerer_api_key) # When response = TestClient(app.test_client()).patch( "/v2/bookings/cancel/token/{}".format(booking.token), headers={ "Authorization": "Bearer " + api_key, "Origin": "http://localhost" }, ) # Then assert response.status_code == 403 assert response.json["user"] == [ "Vous n'avez pas les droits suffisants pour annuler cette réservation." ]
def create_industrial_thing_products(): logger.info("create_industrial_thing_products") thing_products_by_name = {} thing_type_dicts = [ t for t in get_formatted_active_product_types() if t["type"] == "Thing" ] id_at_providers = 1234 for type_index in range(0, THINGS_PER_TYPE): for (thing_type_dict_index, thing_type_dict) in enumerate(thing_type_dicts): mock_index = (type_index + thing_type_dict_index) % len(MOCK_NAMES) name = "{} / {}".format(thing_type_dict["value"], MOCK_NAMES[mock_index]) is_national = thing_type_dict["onlineOnly"] url = "https://ilestencoretemps.fr/" if thing_type_dict[ "onlineOnly"] else None thing_product = create_product_with_thing_type( author_name=MOCK_AUTHOR_NAMES[mock_index], description=MOCK_DESCRIPTIONS[mock_index], id_at_providers=str(id_at_providers), is_national=is_national, thing_name=MOCK_NAMES[mock_index], thing_type=thing_type_dict["value"], thumb_count=0, url=url, ) extraData = {} extra_data_index = 0 for conditionalField in thing_product.offerType[ "conditionalFields"]: conditional_index = type_index + thing_type_dict_index + extra_data_index if conditionalField in [ "author", "performer", "speaker", "stageDirector" ]: mock_first_name_index = ( type_index + thing_type_dict_index + extra_data_index) % len(MOCK_FIRST_NAMES) mock_first_name = MOCK_FIRST_NAMES[mock_first_name_index] mock_last_name_index = ( type_index + thing_type_dict_index + extra_data_index) % len(MOCK_LAST_NAMES) mock_last_name = MOCK_LAST_NAMES[mock_last_name_index] mock_name = "{} {}".format(mock_first_name, mock_last_name) extraData[conditionalField] = mock_name elif conditionalField == "musicType": music_type_index = conditional_index % len(music_types) music_type = music_types[music_type_index] extraData[conditionalField] = str(music_type["code"]) music_sub_type_index = conditional_index % len( music_type["children"]) music_sub_type = music_type["children"][ music_sub_type_index] extraData["musicSubType"] = str(music_sub_type["code"]) elif conditionalField == "isbn": extraData[conditionalField] = random_token(13) extra_data_index += 1 thing_product.extraData = extraData thing_products_by_name[name] = thing_product id_at_providers += 1 type_index += len(thing_type_dicts) repository.save(*thing_products_by_name.values()) logger.info("created %d thing products", len(thing_products_by_name)) return thing_products_by_name
from pcapi.model_creators.generic_creators import create_payment from pcapi.model_creators.generic_creators import create_stock from pcapi.model_creators.generic_creators import create_user from pcapi.model_creators.generic_creators import create_user_offerer from pcapi.model_creators.generic_creators import create_venue from pcapi.model_creators.specific_creators import create_offer_with_thing_product from pcapi.model_creators.specific_creators import create_stock_with_event_offer from pcapi.models import Booking from pcapi.models import EventType from pcapi.repository import repository from pcapi.utils.token import random_token from tests.conftest import TestClient API_KEY_VALUE = random_token(64) @pytest.mark.usefixtures("db_session") class Returns204: class WithApiKeyAuthTest: def when_api_key_is_provided_and_rights_and_regular_offer(self, app): booking = BookingFactory(token="ABCDEF") offerer = booking.stock.offer.venue.managingOfferer api_key = offers_factories.ApiKeyFactory(offerer=offerer) url = f"/v2/bookings/use/token/{booking.token}" response = TestClient(app.test_client()).patch( url, headers={ "Authorization": f"Bearer {api_key.value}",
def random_hashed_password() -> bytes: return crypto.hash_password(random_token(length=12))
def create_industrial_thing_products(): logger.info("create_industrial_thing_products") thing_products_by_name = {} thing_subcategories = [s for s in subcategories.ALL_SUBCATEGORIES if not s.is_event] id_at_providers = 1234 for product_creation_counter in range(0, THINGS_PER_SUBCATEGORY): for (thing_subcategories_list_index, thing_subcategory) in enumerate(thing_subcategories): mock_index = (product_creation_counter + thing_subcategories_list_index) % len(MOCK_NAMES) name = "{} / {}".format(thing_subcategory.id, MOCK_NAMES[mock_index]) is_online_only = ( thing_subcategory.online_offline_platform == subcategories.OnlineOfflinePlatformChoices.ONLINE.value ) url = "https://ilestencoretemps.fr/" if is_online_only else None thing_product = create_product_with_thing_subcategory( author_name=MOCK_AUTHOR_NAMES[mock_index], description=MOCK_DESCRIPTIONS[mock_index], id_at_providers=str(id_at_providers), is_national=is_online_only, thing_name=MOCK_NAMES[mock_index], thing_subcategory_id=thing_subcategory.id, thumb_count=0, url=url, ) extraData = {} extra_data_index = 0 for conditionalField in thing_product.subcategory.conditional_fields: conditional_index = product_creation_counter + thing_subcategories_list_index + extra_data_index if conditionalField in ["author", "performer", "speaker", "stageDirector"]: mock_first_name_index = ( product_creation_counter + thing_subcategories_list_index + extra_data_index ) % len(MOCK_FIRST_NAMES) mock_first_name = MOCK_FIRST_NAMES[mock_first_name_index] mock_last_name_index = ( product_creation_counter + thing_subcategories_list_index + extra_data_index ) % len(MOCK_LAST_NAMES) mock_last_name = MOCK_LAST_NAMES[mock_last_name_index] mock_name = "{} {}".format(mock_first_name, mock_last_name) extraData[conditionalField] = mock_name elif conditionalField == "musicType": music_type_index = conditional_index % len(music_types) music_type = music_types[music_type_index] extraData[conditionalField] = str(music_type["code"]) music_sub_type_index = conditional_index % len(music_type["children"]) music_sub_type = music_type["children"][music_sub_type_index] extraData["musicSubType"] = str(music_sub_type["code"]) elif conditionalField == "isbn": extraData[conditionalField] = random_token(13) extra_data_index += 1 thing_product.extraData = extraData thing_products_by_name[name] = thing_product id_at_providers += 1 product_creation_counter += len(thing_subcategories) repository.save(*thing_products_by_name.values()) logger.info("created %d thing products", len(thing_products_by_name)) return thing_products_by_name
def random_password() -> bytes: return hash_password(random_token(length=12))
def generate_reset_token(user: User, validity_duration_hours: int = 24) -> None: token = random_token(length=RESET_PASSWORD_TOKEN_LENGTH) user.resetPasswordToken = token user.resetPasswordTokenValidityLimit = datetime.utcnow() + timedelta(hours=validity_duration_hours)
def generate_booking_token() -> str: for _i in range(100): token = random_token() if not token_exists(token): return token raise ValueError("Could not generate new booking token")