def test_list_view_jouve_operator(self, client): jouve_admin = users_factories.UserFactory( isAdmin=False, roles=[users_models.UserRole.JOUVE]) client.with_session_auth(jouve_admin.email) user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) fraud_factories.BeneficiaryFraudResultFactory(user=user) hidden_beneficiary_user = users_factories.BeneficiaryGrant18Factory() fraud_factories.BeneficiaryFraudCheckFactory( user=hidden_beneficiary_user, type=fraud_models.FraudCheckType.JOUVE) fraud_factories.BeneficiaryFraudResultFactory( user=hidden_beneficiary_user) hidden_dms_user = users_factories.BeneficiaryGrant18Factory() fraud_factories.BeneficiaryFraudCheckFactory( user=hidden_dms_user, type=fraud_models.FraudCheckType.DMS) fraud_factories.BeneficiaryFraudResultFactory(user=hidden_dms_user) response = client.get("/pc/back-office/support_beneficiary/") html_response = response.data.decode() assert user.email in html_response assert hidden_beneficiary_user.email not in html_response assert hidden_dms_user.email not in html_response assert response.status_code == 200
def test_jouve_specific_query_filter(self, client): client.with_session_auth(self.jouve_admin.email) fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.JOUVE) fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.DMS) response = client.get("/pc/back-office/beneficiary_fraud") assert "<ul><li>dms</li></ul>" not in response.data.decode()
def test_validator_data(self): user = users_factories.UserFactory() fraud_data = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.DMS) expected = fraud_api.get_source_data(user) assert isinstance(expected, fraud_models.JouveContent) assert expected == fraud_models.JouveContent( **fraud_data.resultContent)
def test_review_ko_does_not_activate_the_beneficiary(self, client): user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) admin = users_factories.AdminFactory() client.with_session_auth(admin.email) with override_settings(IS_PROD=True, SUPER_ADMIN_EMAIL_ADDRESSES=[admin.email]): response = client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is denied", "review": "KO" }, ) assert response.status_code == 302 review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=admin).one_or_none() assert review is not None assert review.author == admin assert review.review == fraud_models.FraudReviewStatus.KO assert user.has_beneficiary_role is False assert subscription_models.SubscriptionMessage.query.count() == 1 message = subscription_models.SubscriptionMessage.query.first() assert message.popOverIcon == subscription_models.PopOverIcon.ERROR assert message.userMessage == "Ton dossier a été rejeté. Tu n'es malheureusement pas éligible au pass culture."
def test_validation_from_jouve_admin(self, client): user = users_factories.UserFactory() check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) jouve_admin = users_factories.UserFactory( isAdmin=False, roles=[users_models.UserRole.JOUVE]) client.with_session_auth(jouve_admin.email) response = client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is granted", "review": "OK" }, ) assert response.status_code == 302 review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=jouve_admin).one_or_none() assert review is not None assert review.author == jouve_admin assert user.has_beneficiary_role is True jouve_content = fraud_models.JouveContent(**check.resultContent) assert user.firstName == jouve_content.firstName assert user.lastName == jouve_content.lastName assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 2016025
def test_validation_prod_requires_super_admin(self, client): user = users_factories.UserFactory() check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) admin = users_factories.AdminFactory() client.with_session_auth(admin.email) with override_settings(IS_PROD=True, SUPER_ADMIN_EMAIL_ADDRESSES=[admin.email]): response = client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is granted", "review": "OK" }, ) assert response.status_code == 302 review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=admin).one_or_none() assert review is not None assert review.author == admin assert user.has_beneficiary_role is True jouve_content = fraud_models.JouveContent(**check.resultContent) assert user.firstName == jouve_content.firstName assert user.lastName == jouve_content.lastName
def test_validation_view_validate_user_from_dms_data_staging(self, client): user = users_factories.UserFactory(dateOfBirth=datetime.utcnow() - relativedelta(years=18, months=2)) check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.DMS) admin = users_factories.AdminFactory() client.with_session_auth(admin.email) response = client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is granted", "review": "OK" }, ) assert response.status_code == 302 review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=admin).one() assert review.review == fraud_models.FraudReviewStatus.OK assert review.reason == "User is granted" user = users_models.User.query.get(user.id) assert user.has_beneficiary_role is True assert len(user.deposits) == 1 dms_content = fraud_models.DMSContent(**check.resultContent) assert user.firstName == dms_content.first_name assert user.lastName == dms_content.last_name assert user.idPieceNumber == dms_content.id_piece_number
def test_database_overwrite(self, check_type, factory_class): content = factory_class() instance = fraud_factories.BeneficiaryFraudCheckFactory( type=check_type, resultContent=content) serialized_data = factory_class._meta.model(**instance.resultContent) assert content == serialized_data
def test_on_identity_fraud_check_result_retry(self): user = users_factories.UserFactory() content = fraud_factories.JouveContentFactory( birthLocationCtrl="OK", bodyBirthDateCtrl="OK", bodyBirthDateLevel=100, bodyFirstnameCtrl="OK", bodyFirstnameLevel=100, bodyNameLevel=100, bodyNameCtrl="OK", bodyPieceNumber="wrong-id-piece-number", bodyPieceNumberCtrl= "KO", # ensure we correctly update this field later in the test bodyPieceNumberLevel=100, creatorCtrl="OK", initialSizeCtrl="OK", ) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.JOUVE, user=user, resultContent=content) fraud_check = fraud_api.admin_update_identity_fraud_check_result( user, "123123123123") fraud_result = fraud_factories.BeneficiaryFraudResultFactory( user=user, status=fraud_models.FraudStatus.SUSPICIOUS, reason="Suspiscious case") fraud_api.on_identity_fraud_check_result(user, fraud_check) fraud_result = fraud_models.BeneficiaryFraudResult.query.get( fraud_result.id) assert fraud_result.status == fraud_models.FraudStatus.OK
def test_update_beneficiary_id_piece_number_from_dms_data_with_existing_beneficiary_import( self, client): user = users_factories.UserFactory() fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.DMS) fraud_factories.BeneficiaryFraudResultFactory( user=user, status=fraud_models.FraudStatus.SUSPICIOUS) dms_data = fraud_check.source_data() beneficiary_import = users_factories.BeneficiaryImportFactory( beneficiary=user, applicationId=dms_data.application_id, sourceId=dms_data.procedure_id, source=pcapi.models.BeneficiaryImportSources.demarches_simplifiees. value, ) users_factories.BeneficiaryImportStatusFactory( beneficiaryImport=beneficiary_import) client.with_session_auth(self.jouve_admin.email) id_piece_number = "123123123123" response = client.post( f"/pc/back-office/support_beneficiary/update/beneficiary/id_piece_number/{user.id}", form={"id_piece_number": id_piece_number}, ) assert response.status_code == 302 assert user.beneficiaryFraudResult.status == fraud_models.FraudStatus.OK assert fraud_check.resultContent["id_piece_number"] == id_piece_number assert user.idPieceNumber == id_piece_number assert user.has_beneficiary_role assert len(user.beneficiaryImports) == 1 assert user.beneficiaryImports[ 0].currentStatus == pcapi.models.ImportStatus.CREATED
def test_detail_view(self, client): admin = users_factories.AdminFactory(email="*****@*****.**") user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory(user=user) fraud_factories.BeneficiaryFraudResultFactory(user=user) client.with_session_auth(admin.email) response = client.get( "/pc/back-office/support_beneficiary/?id={user.id}") assert response.status_code == 200
def test_user_validation_has_email_validated(self, fraud_check_type): user = users_factories.UserFactory(isEmailValidated=False) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_check_type, user=user) fraud_result = fraud_api.on_identity_fraud_check_result( user, fraud_check) assert "L'email de l'utilisateur n'est pas validé" in fraud_result.reason assert fraud_result.status == fraud_models.FraudStatus.KO
def test_user_validation_is_beneficiary(self, fraud_check_type): user = users_factories.BeneficiaryGrant18Factory() fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_check_type, user=user) fraud_result = fraud_api.on_identity_fraud_check_result( user, fraud_check) assert ( "L’utilisateur est déjà bénéfiaire, avec un portefeuille non expiré. Il ne peut pas prétendre au pass culture 18 ans" in fraud_result.reason) assert fraud_result.status == fraud_models.FraudStatus.KO
def test_admin_update_identity_fraud_check_result(self): user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.DMS, user=user, ) fraud_check = fraud_api.admin_update_identity_fraud_check_result( user, "id-piece-number") content = fraud_models.DMSContent(**fraud_check.resultContent) assert content.id_piece_number == "id-piece-number"
def test_previously_validated_user_with_retry(self, fraud_check_type): # The user is already beneficiary, and has already done all the checks but # for any circumstances, someone is trying to redo the validation user = users_factories.BeneficiaryGrant18Factory() fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_check_type, user=user) fraud_result = fraud_factories.BeneficiaryFraudResultFactory( user=user, status=fraud_models.FraudStatus.OK) fraud_api.on_identity_fraud_check_result(user, fraud_check) assert fraud_result.status == fraud_models.FraudStatus.OK
def test_underage_user_validation_has_email_validated(self, age): user = users_factories.UserFactory(isEmailValidated=False) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, user=user, resultContent=fraud_factories.EduconnectContentFactory(age=age), ) fraud_result = fraud_api.on_identity_fraud_check_result( user, fraud_check) assert "L'email de l'utilisateur n'est pas validé" in fraud_result.reason assert fraud_result.status == fraud_models.FraudStatus.KO
def test_user_validation_has_phone_validated(self, phone_status, fraud_check_type): user = users_factories.UserFactory( isEmailValidated=True, phoneValidationStatus=phone_status, ) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_check_type, user=user) fraud_result = fraud_api.on_identity_fraud_check_result( user, fraud_check) assert "Le n° de téléphone de l'utilisateur n'est pas validé" in fraud_result.reason assert fraud_result.status == fraud_models.FraudStatus.KO
def test_list_view(self, client): admin = users_factories.AdminFactory(email="*****@*****.**") client.with_session_auth(admin.email) for review_status in fraud_models.FraudReviewStatus: user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory(user=user) fraud_factories.BeneficiaryFraudResultFactory(user=user) fraud_factories.BeneficiaryFraudReviewFactory(user=user, review=review_status) response = client.get( f"/pc/back-office/support_beneficiary/?search={user.id}") assert response.status_code == 200
def test_age_fraud_check_ok(self, age): fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, resultContent=fraud_factories.EduconnectContentFactory(age=age), ) result = fraud_api.educonnect_fraud_checks( beneficiary_fraud_check=fraud_check) age_check = next( (fraud_check for fraud_check in result if fraud_check.reason_code == fraud_models.FraudReasonCode.AGE_NOT_VALID), None, ) assert not age_check
def test_underage_user_validation_is_beneficiary(self, age): user = users_factories.UnderageBeneficiaryFactory() fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, user=user, resultContent=fraud_factories.EduconnectContentFactory(age=age), ) fraud_result = fraud_api.on_identity_fraud_check_result( user, fraud_check) assert ( "L’utilisateur est déjà bénéfiaire, avec un portefeuille non expiré. Il ne peut pas prétendre au pass culture 15-17 ans" in fraud_result.reason) assert fraud_result.status == fraud_models.FraudStatus.KO
def test_admin_update_identity_fraud_check_result(self): user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.JOUVE, user=user, ) fraud_check = fraud_api.admin_update_identity_fraud_check_result( user, "id-piece-number") content = fraud_models.JouveContent(**fraud_check.resultContent) assert content.bodyPieceNumberLevel == 100 assert content.bodyPieceNumber == "id-piece-number" assert content.bodyPieceNumberCtrl == "OK"
def test_ine_whitelisted_fraud_checks_fail(self): fraud_factories.IneHashWhitelistFactory( ine_hash="identifiantWhitelisté1") fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, resultContent=fraud_factories.EduconnectContentFactory( ine_hash="identifiantWhitelisté2"), ) result = fraud_api.educonnect_fraud_checks(fraud_check) duplicate_ine_check = next( fraud_check for fraud_check in result if fraud_check.reason_code == fraud_models.FraudReasonCode.INE_NOT_WHITELISTED) assert duplicate_ine_check.status == fraud_models.FraudStatus.SUSPICIOUS
def test_age_fraud_check_ko(self, age): fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, resultContent=fraud_factories.EduconnectContentFactory(age=age), ) result = fraud_api.educonnect_fraud_checks( beneficiary_fraud_check=fraud_check) age_check = next(fraud_check for fraud_check in result if fraud_check.reason_code == fraud_models.FraudReasonCode.AGE_NOT_VALID) assert age_check.status == fraud_models.FraudStatus.KO assert ( age_check.detail == f"L'age de l'utilisateur est invalide ({age} ans). Il devrait être parmi [15, 16, 17]" )
def test_delete_user_when_she_has_no_deposit(): admin = users_factories.AdminFactory() user_without_deposit = users_factories.UserFactory( email="*****@*****.**") users_factories.FavoriteFactory(user=user_without_deposit) fraud_factories.BeneficiaryFraudCheckFactory(user=user_without_deposit) fraud_factories.BeneficiaryFraudResultFactory(user=user_without_deposit) fraud_factories.BeneficiaryFraudReviewFactory(user=user_without_deposit, author=admin) deposit = Deposit.query.all() repository.delete(*deposit) suspend_or_delete_from_file( "tests/scripts/beneficiary/users_to_delete_fixture.txt", admin.email, ) assert User.query.all() == [admin]
def test_update_beneficiary_id_piece_number_from_jouve_data(self, client): user = users_factories.UserFactory() content = fraud_factories.JouveContentFactory( birthLocationCtrl="OK", bodyBirthDateCtrl="OK", bodyBirthDateLevel=100, bodyFirstnameCtrl="OK", bodyFirstnameLevel=100, bodyNameLevel=100, bodyNameCtrl="OK", bodyPieceNumber="wrong-id-piece-number", bodyPieceNumberCtrl= "KO", # ensure we correctly update this field later in the test bodyPieceNumberLevel=100, creatorCtrl="OK", initialSizeCtrl="OK", ) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE, resultContent=content) fraud_factories.BeneficiaryFraudResultFactory( user=user, status=fraud_models.FraudStatus.SUSPICIOUS) id_piece_number = "123123123123" client.with_session_auth(self.jouve_admin.email) response = client.post( f"/pc/back-office/support_beneficiary/update/beneficiary/id_piece_number/{user.id}", form={"id_piece_number": id_piece_number}, ) assert response.status_code == 302 assert user.beneficiaryFraudResult.status == fraud_models.FraudStatus.OK assert fraud_check.resultContent["bodyPieceNumberCtrl"] == "OK" assert fraud_check.resultContent["bodyPieceNumber"] == id_piece_number assert user.idPieceNumber == id_piece_number assert user.has_beneficiary_role assert len(user.beneficiaryImports) == 1 assert user.beneficiaryImports[ 0].currentStatus == pcapi.models.ImportStatus.CREATED assert user.beneficiaryImports[ 0].eligibilityType == users_models.EligibilityType.AGE18
def test_duplicates_fraud_checks(self): already_existing_user = users_factories.UnderageBeneficiaryFactory( subscription_age=15) fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, resultContent=fraud_factories.EduconnectContentFactory( first_name=already_existing_user.firstName, last_name=already_existing_user.lastName, birth_date=already_existing_user.dateOfBirth, ), ) result = fraud_api.educonnect_fraud_checks(fraud_check) duplicate_check = next(fraud_check for fraud_check in result if fraud_check.reason_code == fraud_models.FraudReasonCode.DUPLICATE_USER) assert duplicate_check.status == fraud_models.FraudStatus.SUSPICIOUS assert duplicate_check.detail == f"Duplicat de l'utilisateur {already_existing_user.id}"
def test_ine_duplicates_fraud_checks(self): fraud_factories.IneHashWhitelistFactory( ine_hash="ylwavk71o3jiwyla83fxk5pcmmu0ws01") same_ine_user = users_factories.UnderageBeneficiaryFactory( ineHash="ylwavk71o3jiwyla83fxk5pcmmu0ws01") fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( type=fraud_models.FraudCheckType.EDUCONNECT, resultContent=fraud_factories.EduconnectContentFactory( ine_hash=same_ine_user.ineHash), ) result = fraud_api.educonnect_fraud_checks(fraud_check) duplicate_ine_check = next(fraud_check for fraud_check in result if fraud_check.reason_code == fraud_models.FraudReasonCode.DUPLICATE_INE) assert duplicate_ine_check.status == fraud_models.FraudStatus.SUSPICIOUS assert ( duplicate_ine_check.detail == f"L'INE ylwavk71o3jiwyla83fxk5pcmmu0ws01 est déjà pris par l'utilisateur {same_ine_user.id}" )
def test_update_beneficiary_id_piece_number_from_dms_data(self, client): user = users_factories.UserFactory() fraud_check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.DMS) fraud_factories.BeneficiaryFraudResultFactory( user=user, status=fraud_models.FraudStatus.SUSPICIOUS) client.with_session_auth(self.jouve_admin.email) id_piece_number = "123123123123" response = client.post( f"/pc/back-office/support_beneficiary/update/beneficiary/id_piece_number/{user.id}", form={"id_piece_number": id_piece_number}, ) assert response.status_code == 302 assert user.beneficiaryFraudResult.status == fraud_models.FraudStatus.OK assert fraud_check.resultContent["id_piece_number"] == id_piece_number assert user.idPieceNumber == id_piece_number assert user.has_beneficiary_role assert len(user.beneficiaryImports) == 1 assert user.beneficiaryImports[ 0].currentStatus == pcapi.models.ImportStatus.CREATED
def test_return_to_dms(self, client): user = users_factories.UserFactory() fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE) jouve_admin = users_factories.UserFactory( isAdmin=False, roles=[users_models.UserRole.JOUVE]) client.with_session_auth(jouve_admin.email) client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is granted", "review": "REDIRECTED_TO_DMS" }, ) review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=jouve_admin).one_or_none() assert review is not None assert review.author == jouve_admin assert review.review == fraud_models.FraudReviewStatus.REDIRECTED_TO_DMS assert "; Redirigé vers DMS" in review.reason assert user.has_beneficiary_role is False assert len(mails_testing.outbox) == 1 sent_data = mails_testing.outbox[0].sent_data assert sent_data["Vars"]["url"] == settings.DMS_USER_URL assert sent_data["MJ-TemplateID"] == 2958557 assert subscription_models.SubscriptionMessage.query.count() == 1 message = subscription_models.SubscriptionMessage.query.first() assert not message.popOverIcon assert ( message.userMessage == "Nous n'arrivons pas à lire ton document. Consulte l'e-mail envoyé le 30/10/2021 pour plus d'informations." )
def test_validation_view_validate_user_from_jouve_data_staging( self, client): user = users_factories.UserFactory( isBeneficiary=False, dateOfBirth=AGE18_ELIGIBLE_BIRTH_DATE) check = fraud_factories.BeneficiaryFraudCheckFactory( user=user, type=fraud_models.FraudCheckType.JOUVE, resultContent__birthDateTxt=f"{AGE18_ELIGIBLE_BIRTH_DATE:%d/%m/%Y}", ) admin = users_factories.AdminFactory() client.with_session_auth(admin.email) response = client.post( f"/pc/back-office/support_beneficiary/validate/beneficiary/{user.id}", form={ "user_id": user.id, "reason": "User is granted", "review": "OK" }, ) assert response.status_code == 302 review = fraud_models.BeneficiaryFraudReview.query.filter_by( user=user, author=admin).one() assert review.review == fraud_models.FraudReviewStatus.OK assert review.reason == "User is granted" user = users_models.User.query.get(user.id) assert user.has_beneficiary_role is True assert len(user.deposits) == 1 assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 2016025 jouve_content = fraud_models.JouveContent(**check.resultContent) assert user.firstName == jouve_content.firstName assert user.lastName == jouve_content.lastName