def test_add_back_a_delete_bcros(client, jwt, session, keycloak_mock): """Assert different conditions of user deletion.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(user_info=TestUserInfo.user_bcros_active) factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) owner_claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) member = TestAnonymousMembership.generate_random_user(USER) membership = [ member, TestAnonymousMembership.generate_random_user(COORDINATOR) ] UserService.create_user_and_add_membership(membership, org.id, token_info=owner_claims) headers = factory_auth_header(jwt=jwt, claims=owner_claims) member_user_id = IdpHint.BCROS.value + '/' + member.get('username') rv = client.delete(f'/api/v1/users/{member_user_id}', headers=headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT kc_user = KeycloakService.get_user_by_username(member.get('username')) assert kc_user.enabled is False user_model = UserService.find_by_username(member_user_id) assert user_model.as_dict().get('user_status') == UserStatus.INACTIVE.value membership = MembershipModel.find_membership_by_userid( user_model.identifier) assert membership.status == Status.INACTIVE.value
def test_create_user_add_membership_reenable(session, auth_mock, keycloak_mock, monkeypatch): # pylint:disable=unused-argument """Assert that an admin can add a member.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) patch_token_info(claims, monkeypatch) anon_member = TestAnonymousMembership.generate_random_user(USER) membership = [anon_member] users = UserService.create_user_and_add_membership(membership, org.id) user_name = IdpHint.BCROS.value + '/' + membership[0]['username'] assert len(users['users']) == 1 assert users['users'][0]['username'] == user_name assert users['users'][0]['type'] == Role.ANONYMOUS_USER.name members = MembershipModel.find_members_by_org_id(org.id) # staff didnt create members..so count is count of owner+other 1 member assert len(members) == 2 # assert cant be readded users = UserService.create_user_and_add_membership(membership, org.id) assert users['users'][0]['http_status'] == 409 assert users['users'][0]['error'] == 'The username is already taken' # deactivate everything and try again anon_user = UserModel.find_by_username(user_name) anon_user.status = Status.INACTIVE.value anon_user.save() membership_model = MembershipModel.find_membership_by_userid(anon_user.id) membership_model.status = Status.INACTIVE.value update_user_request = KeycloakUser() update_user_request.user_name = membership[0]['username'] update_user_request.enabled = False KeycloakService.update_user(update_user_request) org2 = factory_org_model(org_info=TestOrgInfo.org_anonymous_2, org_type_info={'code': 'BASIC'}, org_status_info=None, payment_type_info=None) factory_membership_model(user.id, org2.id) factory_product_model(org2.id, product_code=ProductCode.DIR_SEARCH.value) users = UserService.create_user_and_add_membership(membership, org2.id) assert users['users'][0]['http_status'] == 409 assert users['users'][0]['error'] == 'The username is already taken' # add to same org.Should work users = UserService.create_user_and_add_membership(membership, org.id) assert len(users['users']) == 1 assert users['users'][0][ 'username'] == IdpHint.BCROS.value + '/' + membership[0]['username'] assert users['users'][0]['type'] == Role.ANONYMOUS_USER.name
def test_create_user_and_add_membership_member_error_skip_auth_mode(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that an member cannot be added as anonymous in single_mode mode.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [TestAnonymousMembership.generate_random_user(USER)] with pytest.raises(BusinessException) as exception: UserService.create_user_and_add_membership(membership, org.id, single_mode=True) assert exception.value.code == Error.INVALID_USER_CREDENTIALS.name
def test_reset_password(client, jwt, session, keycloak_mock): # pylint:disable=unused-argument """Assert that an anonymous admin can be Patched.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(user_info=TestUserInfo.user_bcros_active) factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) owner_claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) member = TestAnonymousMembership.generate_random_user(USER) admin = TestAnonymousMembership.generate_random_user(COORDINATOR) membership = [member, admin] UserService.create_user_and_add_membership(membership, org.id, token_info=owner_claims) owner_headers = factory_auth_header(jwt=jwt, claims=owner_claims) member_username = IdpHint.BCROS.value + '/' + member['username'] admin_username = IdpHint.BCROS.value + '/' + admin['username'] admin_claims = TestJwtClaims.get_test_real_user( uuid.uuid4(), admin_username, access_ype=AccessType.ANONYMOUS.value) admin_headers = factory_auth_header(jwt=jwt, claims=admin_claims) member_claims = TestJwtClaims.get_test_real_user( uuid.uuid4(), member_username, access_ype=AccessType.ANONYMOUS.value) member_headers = factory_auth_header(jwt=jwt, claims=member_claims) # set up JWTS for member and admin client.post('/api/v1/users', headers=admin_headers, content_type='application/json') client.post('/api/v1/users', headers=member_headers, content_type='application/json') # reset password of admin by owner input_data = json.dumps({ 'username': admin_username, 'password': '******' }) rv = client.patch(f'/api/v1/users/{admin_username}', headers=owner_headers, data=input_data, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT # member cant reset password rv = client.patch(f'/api/v1/users/{admin_username}', headers=member_headers, data=input_data, content_type='application/json') assert rv.status_code == http_status.HTTP_403_FORBIDDEN # admin cant reset password rv = client.patch(f'/api/v1/users/{admin_username}', headers=admin_headers, data=input_data, content_type='application/json') assert rv.status_code == http_status.HTTP_403_FORBIDDEN
def test_create_user_and_add_membership_admin_bulk_mode_unauthorised(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that bulk operation cannot be performed by unauthorised users.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) membership = [TestAnonymousMembership.generate_random_user(USER)] with pytest.raises(HTTPException) as excinfo: UserService.create_user_and_add_membership(membership, org.id, token_info=TestJwtClaims.public_user_role) assert excinfo.value.code == 403
def test_create_user_and_add_membership_multiple_error_skip_auth_mode( session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that multiple user cannot be created in skip_auth mode.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [ TestAnonymousMembership.generate_random_user(MEMBER), TestAnonymousMembership.generate_random_user(ADMIN) ] with pytest.raises(BusinessException) as exception: UserService.create_user_and_add_membership( membership, org.id, TestJwtClaims.public_user_role, skip_auth=True) assert exception.value.code == Error.INVALID_USER_CREDENTIALS.name
def test_create_user_and_add_same_user_name_error_in_kc( session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that same user name cannot be added twice.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [TestAnonymousMembership.generate_random_user(OWNER)] UserService.create_user_and_add_membership(membership, org.id, skip_auth=True) with pytest.raises(BusinessException) as exception: UserService.create_user_and_add_membership(membership, org.id, skip_auth=True) assert exception.value.code == Error.FAILED_ADDING_USER_IN_KEYCLOAK.name
def test_delete_bcros_valdiations(client, jwt, session, keycloak_mock): """Assert different conditions of user deletion.""" admin_user = TestUserInfo.user_bcros_active org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(user_info=TestUserInfo.user_bcros_active) factory_membership_model(user.id, org.id) owner_claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) member = TestAnonymousMembership.generate_random_user(MEMBER) admin = TestAnonymousMembership.generate_random_user(ADMIN) membership = [member, admin] UserService.create_user_and_add_membership(membership, org.id, token_info=owner_claims) owner_headers = factory_auth_header(jwt=jwt, claims=owner_claims) member_username = IdpHint.BCROS.value + '/' + member['username'] admin_username = IdpHint.BCROS.value + '/' + admin['username'] admin_claims = TestJwtClaims.get_test_real_user(uuid.uuid4(), admin_username, access_ype=AccessType.ANONYMOUS.value) admin_headers = factory_auth_header(jwt=jwt, claims=admin_claims) member_claims = TestJwtClaims.get_test_real_user(uuid.uuid4(), member_username, access_ype=AccessType.ANONYMOUS.value) member_headers = factory_auth_header(jwt=jwt, claims=member_claims) # set up JWTS for member and admin client.post('/api/v1/users', headers=admin_headers, content_type='application/json') client.post('/api/v1/users', headers=member_headers, content_type='application/json') # delete only owner ;failure rv = client.delete(f"/api/v1/users/{admin_user['username']}", headers=owner_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # admin trying to delete member: Failure rv = client.delete(f'/api/v1/users/{member_username}', headers=admin_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # member delete admin: failure rv = client.delete(f'/api/v1/users/{admin_username}', headers=member_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # a self delete ;should work ;mimics leave team for anonymous user rv = client.delete(f'/api/v1/users/{member_username}', headers=member_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT rv = client.delete(f'/api/v1/users/{admin_username}', headers=admin_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT # add one more admin new_owner = TestAnonymousMembership.generate_random_user(OWNER) membership = [new_owner] UserService.create_user_and_add_membership(membership, org.id, token_info=owner_claims) rv = client.delete(f"/api/v1/users/{IdpHint.BCROS.value + '/' + new_owner['username']}", headers=owner_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT
def test_create_user_and_add_same_user_name_error_in_db( session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that same user name cannot be added twice.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(TestUserInfo.user_bcros) factory_membership_model(user.id, org.id) new_members = TestAnonymousMembership.generate_random_user(OWNER) new_members['username'] = user.username.replace(f'{IdpHint.BCROS.value}/', '') membership = [new_members] with pytest.raises(BusinessException) as exception: UserService.create_user_and_add_membership(membership, org.id, skip_auth=True) assert exception.value.code == Error.DATA_ALREADY_EXISTS.name
def test_create_user_and_add_membership_admin_bulk_mode_multiple( session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that an admin can add a group of members.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) membership = [ TestAnonymousMembership.generate_random_user(MEMBER), TestAnonymousMembership.generate_random_user(ADMIN) ] users = UserService.create_user_and_add_membership(membership, org.id, token_info=claims) assert len(users['users']) == 2 assert users['users'][0]['username'] == membership[0]['username'] assert users['users'][0]['type'] == 'ANONYMOUS' assert users['users'][1]['username'] == membership[1]['username'] assert users['users'][1]['type'] == 'ANONYMOUS' members = MembershipModel.find_members_by_org_id(org.id) # staff didnt create members..so count is count of owner+other 2 members assert len(members) == 3
def test_create_user_and_add_transaction_membership_1(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert transactions works fine.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [TestAnonymousMembership.generate_random_user(ADMIN)] with patch('auth_api.models.User.flush', side_effect=Exception('mocked error')): users = UserService.create_user_and_add_membership(membership, org.id, single_mode=True) user_name = IdpHint.BCROS.value + '/' + membership[0]['username'] assert len(users['users']) == 1 assert users['users'][0]['username'] == membership[0]['username'] assert users['users'][0]['http_status'] == 500 assert users['users'][0]['error'] == 'Adding User Failed' # make sure no records are created user = UserModel.find_by_username(user_name) assert user is None user = UserModel.find_by_username(membership[0]['username']) assert user is None members = MembershipModel.find_members_by_org_id(org.id) # only one member should be there since its a STAFF created org assert len(members) == 0
def test_create_user_and_add_membership_admin_bulk_mode_multiple( session, auth_mock, keycloak_mock, monkeypatch): # pylint:disable=unused-argument """Assert that an admin can add a group of members.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) membership = [ TestAnonymousMembership.generate_random_user(USER), TestAnonymousMembership.generate_random_user(COORDINATOR) ] patch_token_info(claims, monkeypatch) users = UserService.create_user_and_add_membership(membership, org.id) assert len(users['users']) == 2 assert users['users'][0][ 'username'] == IdpHint.BCROS.value + '/' + membership[0]['username'] assert users['users'][0]['type'] == Role.ANONYMOUS_USER.name assert users['users'][1][ 'username'] == IdpHint.BCROS.value + '/' + membership[1]['username'] assert users['users'][1]['type'] == Role.ANONYMOUS_USER.name members = MembershipModel.find_members_by_org_id(org.id) # staff didnt create members..so count is count of owner+other 2 members assert len(members) == 3
def test_create_user_and_add_same_user_name_error_in_db(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that same user name cannot be added twice.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(TestUserInfo.user_bcros) factory_membership_model(user.id, org.id) new_members = TestAnonymousMembership.generate_random_user(ADMIN) new_members['username'] = user.username.replace(f'{IdpHint.BCROS.value}/', '') membership = [new_members] users = UserService.create_user_and_add_membership(membership, org.id, single_mode=True) assert users['users'][0]['http_status'] == 409 assert users['users'][0]['error'] == 'The username is already taken'
def test_create_user_and_add_same_user_name_error_in_kc(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that same user name cannot be added twice.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [TestAnonymousMembership.generate_random_user(ADMIN)] keycloak_service = KeycloakService() request = KeycloakScenario.create_user_request() request.user_name = membership[0]['username'] keycloak_service.add_user(request) users = UserService.create_user_and_add_membership(membership, org.id, single_mode=True) assert users['users'][0]['http_status'] == 409 assert users['users'][0]['error'] == 'The username is already taken'
def test_reset_password(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that the password can be changed.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) membership = [TestAnonymousMembership.generate_random_user(USER)] users = UserService.create_user_and_add_membership(membership, org.id, token_info=claims) user_name = users['users'][0]['username'] user_info = {'username': user_name, 'password': '******'} kc_user = UserService.reset_password_for_anon_user(user_info, user_name, claims) # cant assert anything else since password wont be gotten back assert kc_user.user_name == user_name.replace(f'{IdpHint.BCROS.value}/', '').lower()
def test_reset_password_by_member(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that the password cant be changed by member.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model() factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) admin_claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) membership = [TestAnonymousMembership.generate_random_user(USER)] users = UserService.create_user_and_add_membership(membership, org.id, token_info=admin_claims) user_name = users['users'][0]['username'] user_info = {'username': user_name, 'password': '******'} with pytest.raises(HTTPException) as excinfo: UserService.reset_password_for_anon_user(user_info, user_name, token_info=TestJwtClaims.public_user_role) assert excinfo.exception.code == 403
def test_create_user_and_add_membership_owner_skip_auth_mode(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that an owner can be added as anonymous.""" org = factory_org_model(org_info=TestOrgInfo.org_anonymous) membership = [TestAnonymousMembership.generate_random_user(ADMIN)] users = UserService.create_user_and_add_membership(membership, org.id, single_mode=True) assert len(users['users']) == 1 assert users['users'][0]['username'] == IdpHint.BCROS.value + '/' + membership[0]['username'] assert users['users'][0]['type'] == Role.ANONYMOUS_USER.name members = MembershipModel.find_members_by_org_id(org.id) # only one member should be there since its a STAFF created org assert len(members) == 1 assert members[0].membership_type_code == ADMIN
def test_delete_bcros_valdiations(client, jwt, session, keycloak_mock, monkeypatch): """Assert different conditions of user deletion.""" admin_user = TestUserInfo.user_bcros_active org = factory_org_model(org_info=TestOrgInfo.org_anonymous) user = factory_user_model(user_info=TestUserInfo.user_bcros_active) factory_membership_model(user.id, org.id) factory_product_model(org.id, product_code=ProductCode.DIR_SEARCH.value) owner_claims = TestJwtClaims.get_test_real_user(user.keycloak_guid) patch_token_info(owner_claims, monkeypatch) member = TestAnonymousMembership.generate_random_user(USER) admin = TestAnonymousMembership.generate_random_user(COORDINATOR) membership = [member, admin] UserService.create_user_and_add_membership(membership, org.id) owner_headers = factory_auth_header(jwt=jwt, claims=owner_claims) member_username = IdpHint.BCROS.value + '/' + member['username'] admin_username = IdpHint.BCROS.value + '/' + admin['username'] admin_claims = TestJwtClaims.get_test_real_user(uuid.uuid4(), admin_username, access_ype=AccessType.ANONYMOUS.value, roles=[Role.ANONYMOUS_USER.value]) admin_headers = factory_auth_header(jwt=jwt, claims=admin_claims) member_claims = TestJwtClaims.get_test_real_user(uuid.uuid4(), member_username, access_ype=AccessType.ANONYMOUS.value, roles=[Role.ANONYMOUS_USER.value]) member_headers = factory_auth_header(jwt=jwt, claims=member_claims) # set up JWTS for member and admin patch_token_info(admin_claims, monkeypatch) client.post('/api/v1/users', headers=admin_headers, content_type='application/json', data=json.dumps({'isLogin': True})) patch_token_info(member_claims, monkeypatch) client.post('/api/v1/users', headers=member_headers, content_type='application/json', data=json.dumps({'isLogin': True})) patch_token_info(owner_claims, monkeypatch) # delete only owner ;failure rv = client.delete(f"/api/v1/users/{admin_user['username']}", headers=owner_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # admin trying to delete member: Failure patch_token_info(admin_claims, monkeypatch) rv = client.delete(f'/api/v1/users/{member_username}', headers=admin_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # member delete admin: failure patch_token_info(member_claims, monkeypatch) rv = client.delete(f'/api/v1/users/{admin_username}', headers=member_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_401_UNAUTHORIZED # a self delete ;should work ;mimics leave team for anonymous user patch_token_info(member_claims, monkeypatch) rv = client.delete(f'/api/v1/users/{member_username}', headers=member_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT patch_token_info(admin_claims, monkeypatch) rv = client.delete(f'/api/v1/users/{admin_username}', headers=admin_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT # add one more admin patch_token_info(owner_claims, monkeypatch) new_owner = TestAnonymousMembership.generate_random_user(ADMIN) membership = [new_owner] UserService.create_user_and_add_membership(membership, org.id) patch_token_info(owner_claims, monkeypatch) rv = client.delete(f"/api/v1/users/{IdpHint.BCROS.value + '/' + new_owner['username']}", headers=owner_headers, content_type='application/json') assert rv.status_code == http_status.HTTP_204_NO_CONTENT