def patch(org_id, membership_id): # pylint:disable=unused-argument """Update a membership record with new member role.""" token = g.jwt_oidc_token_info role = request.get_json().get('role') membership_status = request.get_json().get('status') notify_user = request.get_json().get('notifyUser') updated_fields_dict = {} origin = request.environ.get('HTTP_ORIGIN', 'localhost') try: if role is not None: updated_role = MembershipService.get_membership_type_by_code(role) updated_fields_dict['membership_type'] = updated_role if membership_status is not None: updated_fields_dict['membership_status'] = \ MembershipService.get_membership_status_by_code(membership_status) membership = MembershipService.find_membership_by_id(membership_id, token) is_own_membership = membership.as_dict()['user']['username'] == \ UserService.find_by_jwt_token(token).as_dict()['username'] if not membership: response, status = {'message': 'The requested membership record could not be found.'}, \ http_status.HTTP_404_NOT_FOUND else: response, status = membership.update_membership(updated_fields=updated_fields_dict, token_info=token ).as_dict(), http_status.HTTP_200_OK # if user status changed to active , mail the user if membership_status == Status.ACTIVE.name: membership.send_notification_to_member(origin, NotificationType.MEMBERSHIP_APPROVED.value) elif notify_user and updated_role and updated_role.code != MEMBER and not is_own_membership: membership.send_notification_to_member(origin, NotificationType.ROLE_CHANGED.value) return response, status except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def test_reset(session, auth_mock): # pylint: disable=unused-argument """Assert that can be reset data by the provided token.""" user_with_token = TestUserInfo.user_tester user_with_token['keycloak_guid'] = TestJwtClaims.tester_role['sub'] user = factory_user_model(user_info=user_with_token) org = factory_org_model(user_id=user.id) factory_membership_model(user.id, org.id) entity = factory_entity_model(user_id=user.id) ResetDataService.reset(TestJwtClaims.tester_role) with pytest.raises(BusinessException) as exception: UserService.find_by_jwt_token(user_with_token) assert exception.value.code == Error.DATA_NOT_FOUND.name found_org = OrgService.find_by_org_id(org.id) assert found_org is None found_entity = EntityService.find_by_entity_id(entity.id) assert found_entity is not None dictionary = found_entity.as_dict() assert dictionary['business_identifier'] == TestEntityInfo.entity1[ 'businessIdentifier'] assert not dictionary['pass_code_claimed'] found_memeber = MembershipService.get_members_for_org(org.id) assert found_memeber is None
def get(org_id): """Retrieve the set of members for the given org.""" try: status = request.args.get('status').upper() if request.args.get( 'status') else None roles = request.args.get('roles').upper() if request.args.get( 'roles') else None members = MembershipService.get_members_for_org( org_id, status=status, membership_roles=roles, token_info=g.jwt_oidc_token_info) if members: response, status = {'members': MembershipSchema(exclude=['org']).dump(members, many=True)}, \ http_status.HTTP_200_OK else: response, status = {}, \ http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def get(org_id): """Retrieve the set of members for the given org.""" try: status = request.args.get('status') roles = request.args.get('roles') # Require ADMIN or higher for anything other than Active Members list if status == Status.ACTIVE.name: allowed_roles = CLIENT_AUTH_ROLES else: allowed_roles = CLIENT_ADMIN_ROLES members = MembershipService.get_members_for_org( org_id, status=status, membership_roles=roles, token_info=g.jwt_oidc_token_info, allowed_roles=(*allowed_roles, STAFF)) if members: response, status = {'members': MembershipSchema(exclude=['org']).dump(members, many=True)}, \ http_status.HTTP_200_OK else: response, status = {}, \ http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def test_accept_invitation(session, auth_mock, keycloak_mock, monkeypatch): # pylint:disable=unused-argument """Accept the invitation and add membership from the invitation to the org.""" with patch.object(InvitationService, 'send_invitation', return_value=None): with patch.object(auth, 'check_auth', return_value=True): with patch.object(InvitationService, 'notify_admin', return_value=None): user_with_token = TestUserInfo.user_test user_with_token[ 'keycloak_guid'] = TestJwtClaims.public_user_role['sub'] user = factory_user_model(user_with_token) patch_token_info({'sub': user.keycloak_guid}, monkeypatch) org = OrgService.create_org(TestOrgInfo.org1, user_id=user.id) org_dictionary = org.as_dict() invitation_info = factory_invitation(org_dictionary['id']) user_with_token_invitee = TestUserInfo.user1 user_with_token_invitee[ 'keycloak_guid'] = TestJwtClaims.edit_role_2['sub'] user_invitee = factory_user_model(user_with_token_invitee) new_invitation = InvitationService.create_invitation( invitation_info, User(user_invitee), '') new_invitation_dict = new_invitation.as_dict() InvitationService.accept_invitation(new_invitation_dict['id'], User(user_invitee), '') patch_token_info(TestJwtClaims.public_user_role, monkeypatch) members = MembershipService.get_members_for_org( org_dictionary['id'], 'PENDING_APPROVAL') assert members assert len(members) == 1
def test_accept_invitation_for_govm(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Accept the invitation and add membership from the invitation to the org.""" with patch.object(InvitationService, 'send_invitation', return_value=None): with patch.object(auth, 'check_auth', return_value=True): with patch.object(InvitationService, 'notify_admin', return_value=None): user_with_token = TestUserInfo.user_staff_admin user_with_token[ 'keycloak_guid'] = TestJwtClaims.public_user_role['sub'] user = factory_user_model(user_with_token) org = OrgService.create_org( TestOrgInfo.org_govm, user_id=user.id, token_info=TestJwtClaims.staff_admin_role) org_dictionary = org.as_dict() invitation_info = factory_invitation(org_dictionary['id']) user_with_token_invitee = TestUserInfo.user1 user_with_token_invitee[ 'keycloak_guid'] = TestJwtClaims.edit_role_2['sub'] user_invitee = factory_user_model(user_with_token_invitee) new_invitation = InvitationService.create_invitation( invitation_info, User(user_invitee), {}, '') new_invitation_dict = new_invitation.as_dict() InvitationService.accept_invitation(new_invitation_dict['id'], User(user_invitee), '') members = MembershipService.get_members_for_org( org_dictionary['id'], 'ACTIVE', token_info=TestJwtClaims.staff_admin_role) assert members assert len(members) == 1, 'user gets active membership'
def test_remove_member_removes_group_to_the_user(session, monkeypatch): # pylint:disable=unused-argument """Assert that accepting an invite adds group to the user.""" # Create a user in keycloak keycloak_service = KeycloakService() request = KeycloakScenario.create_user_request() keycloak_service.add_user(request, return_if_exists=True) kc_user = keycloak_service.get_user_by_username(request.user_name) user = factory_user_model(TestUserInfo.get_user_with_kc_guid(kc_guid=kc_user.id)) # Patch token info def token_info(): # pylint: disable=unused-argument; mocks of library methods return { 'sub': str(kc_user.id), 'username': '******', 'realm_access': { 'roles': [ 'edit' ] }, 'product_code': ProductCode.BUSINESS.value } monkeypatch.setattr('auth_api.services.keycloak.KeycloakService._get_token_info', token_info) org = OrgService.create_org(TestOrgInfo.org1, user_id=user.id) # Create another user request = KeycloakScenario.create_user_request() keycloak_service.add_user(request, return_if_exists=True) kc_user2 = keycloak_service.get_user_by_username(request.user_name) user2 = factory_user_model(TestUserInfo.get_user_with_kc_guid(kc_guid=kc_user2.id)) # Add a membership to the user for the org created factory_membership_model(user2.id, org.as_dict().get('id'), member_type='COORDINATOR', member_status=4) # Add a product to org factory_product_model(org.as_dict().get('id'), product_code=ProductCode.BUSINESS.value) # Find the membership and update to ACTIVE membership = MembershipService.get_membership_for_org_and_user(org.as_dict().get('id'), user2.id) active_membership_status = MembershipStatusCodeModel.get_membership_status_by_code(Status.ACTIVE.name) updated_fields = {'membership_status': active_membership_status} MembershipService(membership).update_membership(updated_fields=updated_fields, token_info=token_info()) user_groups = keycloak_service.get_user_groups(user_id=kc_user2.id) groups = [] for group in user_groups: groups.append(group.get('name')) assert GROUP_ACCOUNT_HOLDERS in groups # Find the membership and update to INACTIVE active_membership_status = MembershipStatusCodeModel.get_membership_status_by_code(Status.INACTIVE.name) updated_fields = {'membership_status': active_membership_status} MembershipService(membership).update_membership(updated_fields=updated_fields, token_info=token_info()) user_groups = keycloak_service.get_user_groups(user_id=kc_user2.id) groups = [] for group in user_groups: groups.append(group.get('name')) assert GROUP_ACCOUNT_HOLDERS not in groups
def get(user_id, org_id): # pylint:disable=unused-argument """Find the count of notification remaining.If any details invalid, it returns zero.""" try: # todo use the user_id instead of jwt pending_count = MembershipService.get_pending_member_count_for_org(org_id, token_info=g.jwt_oidc_token_info) response, status = {'count': pending_count}, http_status.HTTP_200_OK except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def test_get_members(session, keycloak_mock): # pylint:disable=unused-argument """Assert that members for an org can be retrieved.""" user_with_token = TestUserInfo.user_test user_with_token['keycloak_guid'] = TestJwtClaims.public_user_role['sub'] user = factory_user_model(user_info=user_with_token) org = OrgService.create_org(TestOrgInfo.org1, user.id) org_dictionary = org.as_dict() response = MembershipService.get_members_for_org(org_dictionary['id'], status='ACTIVE', token_info=TestJwtClaims.public_user_role) assert response assert len(response) == 1 assert response[0].membership_type_code == 'OWNER'
def delete(org_id, membership_id): # pylint:disable=unused-argument """Mark a membership record as inactive. Membership must match current user token.""" try: membership = MembershipService.find_membership_by_id(membership_id) if membership: response, status = membership.deactivate_membership().as_dict(), \ http_status.HTTP_200_OK else: response, status = {'message': 'The requested membership could not be found.'}, \ http_status.HTTP_404_NOT_FOUND except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def test_delete_org_with_members(session, auth_mock, keycloak_mock, monkeypatch): # pylint:disable=unused-argument """Assert that an org can be deleted.""" user_with_token = TestUserInfo.user_test user_with_token['keycloak_guid'] = TestJwtClaims.public_user_role['sub'] user = factory_user_model(user_info=user_with_token) patch_token_info({'sub': user.keycloak_guid}, monkeypatch) org = OrgService.create_org(TestOrgInfo.org1, user.id) user2 = factory_user_model(user_info=TestUserInfo.user2) factory_membership_model(user2.id, org._model.id, member_type='COORDINATOR') user3 = factory_user_model(user_info=TestUserInfo.user3) factory_membership_model(user3.id, org._model.id, member_type='ADMIN') patch_token_info(TestJwtClaims.public_user_role, monkeypatch) patch_pay_account_delete(monkeypatch) org_id = org.as_dict()['id'] OrgService.delete_org(org_id) assert len(MembershipService.get_members_for_org(org_id)) == 0
def test_accept_invitation_for_govm(session, auth_mock, keycloak_mock, monkeypatch): # pylint:disable=unused-argument """Accept the invitation and add membership from the invitation to the org.""" with patch.object(InvitationService, 'send_invitation', return_value=None): with patch.object(auth, 'check_auth', return_value=True): with patch.object(InvitationService, 'notify_admin', return_value=None): user_with_token = TestUserInfo.user_staff_admin user_with_token[ 'keycloak_guid'] = TestJwtClaims.public_user_role['sub'] user = factory_user_model(user_with_token) patch_token_info(TestJwtClaims.staff_admin_role, monkeypatch) org = OrgService.create_org(TestOrgInfo.org_govm, user_id=user.id) org_dictionary = org.as_dict() invitation_info = factory_invitation(org_dictionary['id']) user_with_token_invitee = TestUserInfo.user1 user_with_token_invitee[ 'keycloak_guid'] = TestJwtClaims.edit_role_2['sub'] user_invitee = factory_user_model(user_with_token_invitee) new_invitation = InvitationService.create_invitation( invitation_info, User(user_invitee), '') new_invitation_dict = new_invitation.as_dict() with patch.object(ActivityLogPublisher, 'publish_activity', return_value=None) as mock_alp: InvitationService.accept_invitation( new_invitation_dict['id'], User(user_invitee), '') mock_alp.assert_called_with( Activity( action=ActivityAction.APPROVE_TEAM_MEMBER.value, org_id=ANY, name=ANY, id=ANY, value=ANY)) members = MembershipService.get_members_for_org( org_dictionary['id'], 'ACTIVE') assert members assert len(members) == 1, 'user gets active membership'