Esempio n. 1
0
    def delete_org(
        org_id,
        token_info: Dict = None,
    ):
        """Soft-Deletes an Org.

        It should not be deletable if there are members or business associated with the org
        """
        # Check authorization for the user
        current_app.logger.debug('<org Inactivated')
        check_auth(token_info, one_of_roles=OWNER, org_id=org_id)

        org: OrgModel = OrgModel.find_by_org_id(org_id)
        if not org:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        count_members = len([
            member for member in org.members if member.status in VALID_STATUSES
        ])
        if count_members > 1 or len(org.affiliated_entities) >= 1:
            raise BusinessException(Error.ORG_CANNOT_BE_DISSOLVED, None)

        org.delete()

        # Remove user from thr group if the user doesn't have any other orgs membership
        user = UserModel.find_by_jwt_token(token=token_info)
        if len(MembershipModel.find_orgs_for_user(user.id)) == 0:
            KeycloakService.remove_from_account_holders_group(
                user.keycloak_guid)
        current_app.logger.debug('org Inactivated>')
Esempio n. 2
0
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'] == IdpHint.BCROS.value + '/' + membership[0]['username']
    assert users['users'][0]['type'] == 'ANONYMOUS'
    assert users['users'][1][
        'username'] == IdpHint.BCROS.value + '/' + 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
Esempio n. 3
0
    def create_org(org_info: dict, user_id):
        """Create a new organization."""
        current_app.logger.debug('<create_org ')
        existing_similar__org = OrgModel.find_similar_org_by_name(org_info['name'])
        if existing_similar__org is not None:
            raise BusinessException(Error.DATA_CONFLICT, None)

        org = OrgModel.create_from_dict(camelback2snake(org_info))
        org.save()
        current_app.logger.info(f'<created_org org_id:{org.id}')
        # create the membership record for this user
        membership = MembershipModel(org_id=org.id, user_id=user_id, membership_type_code='OWNER',
                                     membership_type_status=Status.ACTIVE.value)
        membership.save()

        return Org(org)
Esempio n. 4
0
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
Esempio n. 5
0
    def get_invitations_for_org(org_id, status=None, **kwargs):
        """Get invitations for an org."""
        user_from_context: UserContext = kwargs['user_context']
        org_model = OrgModel.find_by_org_id(org_id)
        if not org_model:
            return None

        if status:
            status = InvitationStatus[status]

        # If staff return full list
        if user_from_context.is_staff():
            return InvitationModel.find_pending_invitations_by_org(org_id)

        current_user: UserService = UserService.find_by_jwt_token()
        current_user_membership: MembershipModel = \
            MembershipModel.find_membership_by_user_and_org(user_id=current_user.identifier, org_id=org_id)

        # If no active membership return empty array
        if current_user_membership is None or \
                current_user_membership.status != Status.ACTIVE.value:
            return []

        # Ensure either ADMIN or COORDINATOR
        if current_user_membership.membership_type_code == USER:
            return []

        return InvitationModel.find_invitations_by_org(org_id=org_id,
                                                       status=status)
Esempio n. 6
0
    def get_invitations_for_org(org_id, status=None, token_info: Dict = None):
        """Get invitations for an org."""
        org_model = OrgModel.find_by_org_id(org_id)
        if not org_model:
            return None

        if status:
            status = InvitationStatus[status]

        # If staff return full list
        if 'staff' in token_info.get('realm_access').get('roles'):
            return InvitationModel.find_pending_invitations_by_org(org_id)

        current_user: UserService = UserService.find_by_jwt_token(token_info)
        current_user_membership: MembershipModel = \
            MembershipModel.find_membership_by_user_and_org(user_id=current_user.identifier, org_id=org_id)

        # If no active membership return empty array
        if current_user_membership is None or \
                current_user_membership.status != Status.ACTIVE.value:
            return []

        # Ensure either ADMIN or COORDINATOR
        if current_user_membership.membership_type_code == USER:
            return []

        return InvitationModel.find_invitations_by_org(org_id=org_id, status=status)
Esempio n. 7
0
def test_delete_user_where_org_has_affiliations(session, auth_mock, keycloak_mock):  # pylint:disable=unused-argument
    """Assert that a user can be deleted."""
    user_model = factory_user_model(user_info=TestUserInfo.user_test)
    contact = factory_contact_model()
    contact_link = ContactLinkModel()
    contact_link.contact = contact
    contact_link.user = user_model
    contact_link = contact_link.flush()
    contact_link.commit()

    org = OrgService.create_org(TestOrgInfo.org1, user_id=user_model.id).as_dict()
    org_id = org['id']

    entity = factory_entity_model(entity_info=TestEntityInfo.entity_lear_mock)

    affiliation = AffiliationModel(org_id=org_id, entity_id=entity.id)
    affiliation.save()
    with pytest.raises(BusinessException) as exception:
        UserService.delete_user(TestJwtClaims.user_test)
        assert exception.code == Error.DELETE_FAILED_ONLY_OWNER

    updated_user = UserModel.find_by_jwt_token(TestJwtClaims.user_test)
    contacts = UserService.get_contacts(TestJwtClaims.user_test)
    assert len(contacts) == 1

    user_orgs = MembershipModel.find_orgs_for_user(updated_user.id)
    for org in user_orgs:
        assert org.status_code == 'ACTIVE'
Esempio n. 8
0
    def reset_password_for_anon_user(user_info: dict,
                                     user_name,
                                     token_info: Dict = None):
        """Reset the password of the user."""
        user = UserModel.find_by_username(user_name)
        membership = MembershipModel.find_membership_by_userid(user.id)
        org_id = membership.org_id
        org = OrgModel.find_by_org_id(org_id)
        if not org or org.access_type != AccessType.ANONYMOUS.value:
            raise BusinessException(Error.INVALID_INPUT, None)

        check_auth(org_id=org_id,
                   token_info=token_info,
                   one_of_roles=(ADMIN, STAFF))
        update_user_request = KeycloakUser()
        update_user_request.user_name = user_name.replace(
            IdpHint.BCROS.value + '/', '')
        update_user_request.password = user_info['password']
        update_user_request.update_password_on_login()

        try:
            kc_user = KeycloakService.update_user(update_user_request)
        except HTTPError as err:
            current_app.logger.error('update_user in keycloak failed {}', err)
            raise BusinessException(Error.UNDEFINED_ERROR, err)
        return kc_user
Esempio n. 9
0
    def get_admins_for_membership(membership_id, status=Status.ACTIVE.value):
        """Get admins for an org."""
        membership = MembershipModel.find_membership_by_id(membership_id)
        org_id = membership.org_id

        return UserModel.find_users_by_org_id_by_status_by_roles(
            org_id, CLIENT_ADMIN_ROLES, status)
Esempio n. 10
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
Esempio n. 11
0
 def __remove_org_membership(org, user_id):
     is_user_an_owner: bool = False
     org_has_other_owners: bool = False
     user_membership: MembershipModel = None
     for member in MembershipModel.find_members_by_org_id(org.id):
         if member.user_id == user_id:
             user_membership = member
             if member.membership_type_code == OWNER:
                 is_user_an_owner = True
         elif member.membership_type_code == OWNER:
             org_has_other_owners = True
     current_app.logger.info(
         f'Org :{org.name} --> User Owner : {is_user_an_owner},Has other owners :{org_has_other_owners}'
     )
     if is_user_an_owner and not org_has_other_owners:
         current_app.logger.info('Affiliated entities : {}'.format(
             len(org.affiliated_entities)))
         if len(org.affiliated_entities) == 0:
             org.status_code = OrgStatus.INACTIVE.value
             org.flush()
         else:
             # Roll back the transaction as there could be situation where a change in one org
             # membership is flushed, but the next one fails. In this case roll back whole transaction
             org.rollback()
             raise BusinessException(Error.DELETE_FAILED_ONLY_OWNER, None)
     else:
         user_membership.status = Status.INACTIVE.value
         user_membership.flush()
Esempio n. 12
0
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
Esempio n. 13
0
 def _add_or_remove_group(model: MembershipModel):
     """Add or remove the user from/to account holders group."""
     if model.membership_status.id == Status.ACTIVE.value:
         KeycloakService.join_account_holders_group(model.user.keycloak_guid)
     elif model.membership_status.id == Status.INACTIVE.value and len(
             MembershipModel.find_orgs_for_user(model.user.id)) == 0:
         # Check if the user has any other active org membership, if none remove from the group
         KeycloakService.remove_from_account_holders_group(model.user.keycloak_guid)
Esempio n. 14
0
def test_delete_user_where_user_is_member_on_org(session, auth_mock,
                                                 keycloak_mock, monkeypatch):  # pylint:disable=unused-argument
    """Assert that a user can be deleted."""
    # Create a user and org
    user_model = factory_user_model(user_info=TestUserInfo.user_test)
    contact = factory_contact_model()
    contact_link = ContactLinkModel()
    contact_link.contact = contact
    contact_link.user = user_model
    contact_link.commit()

    patch_token_info(TestJwtClaims.get_test_user(user_model.keycloak_guid),
                     monkeypatch)
    org = OrgService.create_org(TestOrgInfo.org1, user_id=user_model.id)
    org_dictionary = org.as_dict()
    org_id = org_dictionary['id']

    entity = factory_entity_model(entity_info=TestEntityInfo.entity_lear_mock)
    affiliation = AffiliationModel(org_id=org_id, entity_id=entity.id)
    affiliation.save()

    # Create another user and add membership to the above org
    user_model2 = factory_user_model(user_info=TestUserInfo.user2)
    contact = factory_contact_model()
    contact_link = ContactLinkModel()
    contact_link.contact = contact
    contact_link.user = user_model2
    contact_link.commit()

    membership = MembershipModel(org_id=org_id,
                                 user_id=user_model2.id,
                                 membership_type_code='USER',
                                 membership_type_status=Status.ACTIVE.value)
    membership.save()

    patch_token_info(TestJwtClaims.get_test_user(user_model2.keycloak_guid),
                     monkeypatch)
    UserService.delete_user()

    updated_user = UserModel.find_by_jwt_token()
    assert len(updated_user.contacts) == 0

    user_orgs = MembershipModel.find_orgs_for_user(updated_user.id)
    for org in user_orgs:
        assert org.status_code == 'INACTIVE'
Esempio n. 15
0
    def _create_new_user_and_membership(db_username, kc_user, membership,
                                        org_id):
        user_model: UserModel = UserModel(username=db_username,
                                          is_terms_of_use_accepted=False,
                                          status=Status.ACTIVE.value,
                                          type=AccessType.ANONYMOUS.value,
                                          email=membership.get('email', None),
                                          firstname=kc_user.first_name,
                                          lastname=kc_user.last_name)
        user_model.flush()
        membership_model = MembershipModel(
            org_id=org_id,
            user_id=user_model.id,
            membership_type_code=membership['membershipType'],
            membership_type_status=Status.ACTIVE.value)

        membership_model.flush()
        return user_model
Esempio n. 16
0
    def get_members_for_org(
            org_id,
            status=Status.ACTIVE.name,  # pylint:disable=too-many-return-statements
            membership_roles=ALL_ALLOWED_ROLES,
            **kwargs):
        """Get members of org.Fetches using status and roles."""
        org_model = OrgModel.find_by_org_id(org_id)
        if not org_model:
            return None

        user_from_context: UserContext = kwargs['user_context']
        status = Status.ACTIVE.value if status is None else Status[status].value
        membership_roles = ALL_ALLOWED_ROLES if membership_roles is None else membership_roles
        # If staff return full list
        if user_from_context.is_staff():
            return MembershipModel.find_members_by_org_id_by_status_by_roles(
                org_id, membership_roles, status)

        current_user: UserService = UserService.find_by_jwt_token()
        current_user_membership: MembershipModel = \
            MembershipModel.find_membership_by_user_and_org(user_id=current_user.identifier, org_id=org_id)

        # If no active or pending membership return empty array
        if current_user_membership is None or \
                current_user_membership.status == Status.INACTIVE.value or \
                current_user_membership.status == Status.REJECTED.value:
            return []

        # If pending approval, return empty for active, array of self only for pending
        if current_user_membership.status == Status.PENDING_APPROVAL.value:
            return [current_user_membership
                    ] if status == Status.PENDING_APPROVAL.value else []

        # If active status for current user, then check organizational role
        if current_user_membership.status == Status.ACTIVE.value:
            if current_user_membership.membership_type_code in (ADMIN,
                                                                COORDINATOR):
                return MembershipModel.find_members_by_org_id_by_status_by_roles(
                    org_id, membership_roles, status)

            return MembershipModel.find_members_by_org_id_by_status_by_roles(org_id, membership_roles, status) \
                if status == Status.ACTIVE.value else []

        return []
Esempio n. 17
0
    def get_members_for_org(
            org_id,
            status=Status.ACTIVE,  # pylint:disable=too-many-return-statements
            membership_roles=ALL_ALLOWED_ROLES,
            token_info: Dict = None):
        """Get members of org.Fetches using status and roles."""
        org_model = OrgModel.find_by_org_id(org_id)
        if not org_model:
            return None

        status = Status.ACTIVE.value if status is None else Status[status].value
        membership_roles = ALL_ALLOWED_ROLES if membership_roles is None else membership_roles

        # If staff return full list
        if 'staff' in token_info.get('realm_access').get('roles'):
            return MembershipModel.find_members_by_org_id_by_status_by_roles(
                org_id, membership_roles, status)

        current_user: UserService = UserService.find_by_jwt_token(token_info)
        current_user_membership: MembershipModel = \
            MembershipModel.find_membership_by_user_and_org(user_id=current_user.identifier, org_id=org_id)

        # If no active or pending membership return empty array
        if current_user_membership is None or \
                current_user_membership.status == Status.INACTIVE.value or \
                current_user_membership.status == Status.REJECTED.value:
            return []

        # If pending approval, return empty for active, array of self only for pending
        if current_user_membership.status == Status.PENDING_APPROVAL.value:
            return [current_user_membership
                    ] if status == Status.PENDING_APPROVAL.value else []

        # If active status for current user, then check organizational role
        if current_user_membership.status == Status.ACTIVE.value:
            if current_user_membership.membership_type_code == ADMIN or \
                    current_user_membership.membership_type_code == COORDINATOR:
                return MembershipModel.find_members_by_org_id_by_status_by_roles(
                    org_id, membership_roles, status)

            return MembershipModel.find_members_by_org_id_by_status_by_roles(org_id, membership_roles, status) \
                if status == Status.ACTIVE.value else []

        return []
Esempio n. 18
0
    def _create_new_user_and_membership(db_username, kc_user, membership, org_id):
        user_model: UserModel = UserModel(username=db_username,
                                          is_terms_of_use_accepted=False, status=Status.ACTIVE.value,
                                          type=Role.ANONYMOUS_USER.name,
                                          email=membership.get('email', None),
                                          firstname=kc_user.first_name, lastname=kc_user.last_name,
                                          login_source=LoginSource.BCROS.value)
        user_model.flush()
        membership_model = MembershipModel(org_id=org_id, user_id=user_model.id,
                                           membership_type_code=membership['membershipType'],
                                           membership_type_status=Status.ACTIVE.value)

        membership_model.flush()
        name = {'first_name': user_model.firstname, 'last_name': user_model.lastname}
        ActivityLogPublisher.publish_activity(Activity(org_id, ActivityAction.APPROVE_TEAM_MEMBER.value,
                                                       name=json.dumps(name),
                                                       value=membership['membershipType'],
                                                       id=user_model.id))
        return user_model
Esempio n. 19
0
    def create_org(org_info: dict, user_id, token_info: Dict = None):
        """Create a new organization."""
        current_app.logger.debug('<create_org ')
        is_staff_admin = token_info and 'staff_admin' in token_info.get(
            'realm_access').get('roles')
        if not is_staff_admin:  # staff can create any number of orgs
            count = OrgModel.get_count_of_org_created_by_user_id(user_id)
            if count >= current_app.config.get('MAX_NUMBER_OF_ORGS'):
                raise BusinessException(Error.MAX_NUMBER_OF_ORGS_LIMIT, None)
            if org_info.get('accessType', None) == AccessType.ANONYMOUS.value:
                raise BusinessException(Error.USER_CANT_CREATE_ANONYMOUS_ORG,
                                        None)

        existing_similar__org = OrgModel.find_similar_org_by_name(
            org_info['name'])
        if existing_similar__org is not None:
            raise BusinessException(Error.DATA_CONFLICT, None)
        org = OrgModel.create_from_dict(camelback2snake(org_info))
        if is_staff_admin:
            org.access_type = AccessType.ANONYMOUS.value
            org.billable = False
        else:
            org.access_type = AccessType.BCSC.value
            org.billable = True
        org.save()
        current_app.logger.info(f'<created_org org_id:{org.id}')
        # create the membership record for this user if its not created by staff and access_type is anonymous
        if not is_staff_admin and org_info.get(
                'access_type') != AccessType.ANONYMOUS:
            membership = MembershipModel(
                org_id=org.id,
                user_id=user_id,
                membership_type_code='OWNER',
                membership_type_status=Status.ACTIVE.value)
            membership.save()

            # Add the user to account_holders group
            KeycloakService.join_account_holders_group()

        # TODO Remove later, create payment settings now with default values
        AccountPaymentModel.create_from_dict({'org_id': org.id})

        return Org(org)
Esempio n. 20
0
    def accept_invitation(invitation_id, user: UserService, origin, add_membership: bool = True,
                          token_info: Dict = None):
        """Add user, role and org from the invitation to membership."""
        current_app.logger.debug('>accept_invitation')
        invitation: InvitationModel = InvitationModel.find_invitation_by_id(invitation_id)

        if invitation is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        if invitation.invitation_status_code == 'ACCEPTED':
            raise BusinessException(Error.ACTIONED_INVITATION, None)
        if invitation.invitation_status_code == 'EXPIRED':
            raise BusinessException(Error.EXPIRED_INVITATION, None)

        if getattr(token_info, 'loginSource', None) is not None:  # bcros comes with out token
            login_source = token_info.get('loginSource', None)
            if invitation.login_source != login_source:
                raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)

        if add_membership:
            for membership in invitation.membership:
                membership_model = MembershipModel()
                membership_model.org_id = membership.org_id
                membership_model.user_id = user.identifier
                membership_model.membership_type = membership.membership_type

                # check to ensure an invitation for this user/org has not already been processed
                existing_membership = MembershipService \
                    .get_membership_for_org_and_user(org_id=membership_model.org_id, user_id=membership_model.user_id)

                if existing_membership:
                    raise BusinessException(Error.DATA_ALREADY_EXISTS, None)
                org_model: OrgModel = OrgModel.find_by_org_id(membership.org_id)

                # GOVM users gets direct approval since they are IDIR users.
                membership_model.status = Invitation._get_status_based_on_org(org_model)
                membership_model.save()
                try:
                    Invitation.notify_admin(user, invitation_id, membership_model.id, origin)
                except BusinessException as exception:
                    current_app.logger.error('<send_notification_to_admin failed', exception.message)
        invitation.accepted_date = datetime.now()
        invitation.invitation_status = InvitationStatusModel.get_status_by_code('ACCEPTED')
        invitation.save()

        # Call keycloak to add the user to the group.
        if user:
            group_name: str = KeycloakService.join_users_group(token_info)
            KeycloakService.join_account_holders_group(user.keycloak_guid)

            if group_name == GROUP_GOV_ACCOUNT_USERS:
                # TODO Remove this if gov account users needs Terms of Use.
                tos_document = DocumentsModel.fetch_latest_document_by_type(DocumentType.TERMS_OF_USE.value)
                user.update_terms_of_use(token_info, True, tos_document.version_id)
                # Add contact to the user.
                user.add_contact(token_info, dict(email=token_info.get('email', None)))

        current_app.logger.debug('<accept_invitation')
        return Invitation(invitation)
Esempio n. 21
0
    def _modify_task(user):
        """Clone on-hold task to a new active task; handle user-based and org-based tasks."""
        # find users org. ideally only one org
        org_list = MembershipModel.find_orgs_for_user(user.identifier)
        org: OrgModel = next(iter(org_list or []), None)
        if org:
            # check if there is any holding tasks
            # Find if the corresponding task is NEW_ACCOUNT_STAFF_REVIEW / GOVN type, clone and close it
            task_model: TaskModel = TaskModel.find_by_task_for_account(
                org.id, TaskStatus.HOLD.value)
            if task_model is None:
                # Else, find if there are any associated task of BCEID_ADMIN type, clone and close it
                task_model: TaskModel = TaskModel.find_by_user_and_status(
                    org.id, TaskStatus.HOLD.value)

            if task_model:
                task_info = {
                    'name':
                    org.name,
                    'relationshipId':
                    task_model.relationship_id,
                    'relatedTo':
                    user.identifier,
                    'dateSubmitted':
                    task_model.date_submitted,
                    'relationshipType':
                    task_model.relationship_type,
                    'type':
                    task_model.type,
                    'action':
                    task_model.action,
                    'status':
                    TaskStatus.OPEN.value,
                    'relationship_status':
                    TaskRelationshipStatus.PENDING_STAFF_REVIEW.value,
                    'account_id':
                    task_model.account_id
                }
                new_task = TaskService.create_task(task_info=task_info,
                                                   do_commit=False)

                # Send notification mail to staff review task
                from auth_api.services import Org as OrgService  # pylint:disable=cyclic-import, import-outside-toplevel
                if task_model.relationship_type == TaskRelationshipType.USER.value:
                    OrgService.send_staff_review_account_reminder(
                        relationship_id=user.identifier,
                        task_relationship_type=TaskRelationshipType.USER.value)
                else:
                    OrgService.send_staff_review_account_reminder(
                        relationship_id=org.id)

                remarks = [
                    f'User Uploaded New affidavit .Created New task id: {new_task.identifier}'
                ]
                TaskService.close_task(task_model.id, remarks)
Esempio n. 22
0
    def accept_invitation(invitation_id,
                          user,
                          origin,
                          add_membership: bool = True):
        """Add user, role and org from the invitation to membership."""
        current_app.logger.debug('>accept_invitation')
        invitation: InvitationModel = InvitationModel.find_invitation_by_id(
            invitation_id)

        if invitation is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        if invitation.invitation_status_code == 'ACCEPTED':
            raise BusinessException(Error.ACTIONED_INVITATION, None)
        if invitation.invitation_status_code == 'EXPIRED':
            raise BusinessException(Error.EXPIRED_INVITATION, None)

        if add_membership:
            for membership in invitation.membership:
                membership_model = MembershipModel()
                membership_model.org_id = membership.org_id
                membership_model.user_id = user.identifier
                membership_model.membership_type = membership.membership_type

                # check to ensure an invitation for this user/org has not already been processed
                existing_membership = MembershipService \
                    .get_membership_for_org_and_user(org_id=membership_model.org_id, user_id=membership_model.user_id)

                if existing_membership:
                    raise BusinessException(Error.DATA_ALREADY_EXISTS, None)

                # user needs to get approval
                is_auto_approval = OrgSettingsModel.is_admin_auto_approved_invitees(
                    membership.org_id)
                if is_auto_approval:
                    membership_model.status = Status.ACTIVE.value
                else:
                    membership_model.status = Status.PENDING_APPROVAL.value
                membership_model.save()
                if not is_auto_approval:
                    try:
                        Invitation.notify_admin(user, invitation_id,
                                                membership_model.id, origin)
                    except BusinessException as exception:
                        current_app.logger.error(
                            '<send_notification_to_admin failed',
                            exception.message)
        invitation.accepted_date = datetime.now()
        invitation.invitation_status = InvitationStatusModel.get_status_by_code(
            'ACCEPTED')
        invitation.save()
        current_app.logger.debug('<accept_invitation')
        return Invitation(invitation)
Esempio n. 23
0
def test_delete_user_is_member_returns_204(client, jwt, session,
                                           keycloak_mock):  # pylint:disable=unused-argument
    """Test if the user is the member of a team assert status is 204."""
    user_model = factory_user_model(user_info=TestUserInfo.user_test)
    contact = factory_contact_model()
    contact_link = ContactLinkModel()
    contact_link.contact = contact
    contact_link.user = user_model
    contact_link.commit()

    user_model2 = factory_user_model(user_info=TestUserInfo.user2)
    contact = factory_contact_model()
    contact_link = ContactLinkModel()
    contact_link.contact = contact
    contact_link.user = user_model2
    contact_link.commit()

    claims = copy.deepcopy(TestJwtClaims.public_user_role.value)
    claims['sub'] = str(user_model2.keycloak_guid)

    org = OrgService.create_org(TestOrgInfo.org1,
                                user_id=user_model.id,
                                token_info=claims)
    org_dictionary = org.as_dict()
    org_id = org_dictionary['id']

    entity = factory_entity_model(entity_info=TestEntityInfo.entity_lear_mock)
    affiliation = AffiliationModel(org_id=org_id, entity_id=entity.id)
    affiliation.save()

    membership = MembershipModel(org_id=org_id,
                                 user_id=user_model2.id,
                                 membership_type_code='USER',
                                 membership_type_status=Status.ACTIVE.value)
    membership.save()

    headers = factory_auth_header(jwt=jwt, claims=claims)

    rv = client.delete('/api/v1/users/@me',
                       headers=headers,
                       content_type='application/json')
    assert rv.status_code == http_status.HTTP_204_NO_CONTENT
Esempio n. 24
0
    def find_membership_by_id(cls, membership_id, token_info: Dict = None):
        """Retrieve a membership record by id."""
        membership = MembershipModel.find_membership_by_id(membership_id)

        if membership:
            # Ensure that this user is an ADMIN or OWNER on the org associated with this membership
            # or that the membership is for the current user
            if membership.user.username != token_info.get('username'):
                check_auth(org_id=membership.org_id, token_info=token_info, one_of_roles=(ADMIN, OWNER))
            return Membership(membership)
        return None
Esempio n. 25
0
    def find_membership_by_id(cls, membership_id, **kwargs):
        """Retrieve a membership record by id."""
        user_from_context: UserContext = kwargs['user_context']
        membership = MembershipModel.find_membership_by_id(membership_id)

        if membership:
            # Ensure that this user is an COORDINATOR or ADMIN on the org associated with this membership
            # or that the membership is for the current user
            if membership.user.username != user_from_context.user_name:
                check_auth(org_id=membership.org_id,
                           one_of_roles=(COORDINATOR, ADMIN, STAFF))
            return Membership(membership)
        return None
Esempio n. 26
0
 def delete_otp_for_user(user_name, origin_url: str = None):
     """Reset the OTP of the user."""
     # TODO - handle when the multiple teams implemented for bceid..
     user = UserModel.find_by_username(user_name)
     membership = MembershipModel.find_membership_by_userid(user.id)
     org_id = membership.org_id
     check_auth(org_id=org_id, one_of_roles=(ADMIN, COORDINATOR, STAFF))
     try:
         KeycloakService.reset_otp(str(user.keycloak_guid))
         User.send_otp_authenticator_reset_notification(user.email, origin_url, org_id)
     except HTTPError as err:
         current_app.logger.error('update_user in keycloak failed {}', err)
         raise BusinessException(Error.UNDEFINED_ERROR, err) from err
Esempio n. 27
0
    def accept_invitation(invitation_id,
                          user,
                          origin,
                          add_membership: bool = True,
                          token_info: Dict = None):
        """Add user, role and org from the invitation to membership."""
        current_app.logger.debug('>accept_invitation')
        invitation: InvitationModel = InvitationModel.find_invitation_by_id(
            invitation_id)

        if invitation is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        if invitation.invitation_status_code == 'ACCEPTED':
            raise BusinessException(Error.ACTIONED_INVITATION, None)
        if invitation.invitation_status_code == 'EXPIRED':
            raise BusinessException(Error.EXPIRED_INVITATION, None)

        if getattr(token_info, 'loginSource',
                   None) is not None:  # bcros comes with out token
            login_source = token_info.get('loginSource', None)
            if invitation.login_source != login_source:
                raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)

        if add_membership:
            for membership in invitation.membership:
                membership_model = MembershipModel()
                membership_model.org_id = membership.org_id
                membership_model.user_id = user.identifier
                membership_model.membership_type = membership.membership_type

                # check to ensure an invitation for this user/org has not already been processed
                existing_membership = MembershipService \
                    .get_membership_for_org_and_user(org_id=membership_model.org_id, user_id=membership_model.user_id)

                if existing_membership:
                    raise BusinessException(Error.DATA_ALREADY_EXISTS, None)

                membership_model.status = Status.PENDING_APPROVAL.value
                membership_model.save()
                try:
                    Invitation.notify_admin(user, invitation_id,
                                            membership_model.id, origin)
                except BusinessException as exception:
                    current_app.logger.error(
                        '<send_notification_to_admin failed',
                        exception.message)
        invitation.accepted_date = datetime.now()
        invitation.invitation_status = InvitationStatusModel.get_status_by_code(
            'ACCEPTED')
        invitation.save()
        current_app.logger.debug('<accept_invitation')
        return Invitation(invitation)
Esempio n. 28
0
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
Esempio n. 29
0
    def get_orgs(user_id):
        """Return the orgs associated with this user."""
        # TODO DO_NOT_USE this def if there is a database transaction involved,
        # as the below logic removes object from model
        orgs = MembershipModel.find_orgs_for_user(user_id)
        # because members are fetched using backpopulates,cant add these conditions programmatically.
        # so resorting to manually looping   # noqa:E501

        for org in orgs:
            # user can have multiple memberships.if the user getting denied first and added again,
            # it will be multiple memberships..filter out denied records # noqa:E501
            # fix for https://github.com/bcgov/entity/issues/1951   # noqa:E501
            org.members = list(
                filter(lambda member: (member.user_id == user_id and (member.status in VALID_STATUSES)), org.members))
        return orgs
Esempio n. 30
0
    def delete_user(token):
        """Delete User Profile.

        Does the following
        1) Find the user using token
        2) Find all org membership for the user
        3) Check if the current user is the only owner for any org - If yes, deny the action
        4) Mark the membership as inactive on all orgs for the user
        5) Delete the contact information for the user and the accepted terms of service
        6) Mark the user record as inactive
        """
        current_app.logger.debug('<delete_user')

        user: UserModel = UserModel.find_by_jwt_token(token)
        if not user:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        if user.status == UserStatus.INACTIVE.value:
            raise BusinessException(Error.DELETE_FAILED_INACTIVE_USER, None)

        user_orgs: List[OrgModel] = MembershipModel.find_orgs_for_user(user.id)

        current_app.logger.info('Found {} orgs for the user'.format(
            len(user_orgs) if user_orgs else 0))

        if user_orgs:
            for org in user_orgs:
                current_app.logger.debug(
                    f'Org : {org.name},  Status : {org.status_code}')
                if org.status_code == Status.ACTIVE.name:
                    User.__remove_org_membership(org, user.id)

        # Delete contact
        User.__delete_contact(user=user)

        # Set the user status as inactive
        user.status = UserStatus.INACTIVE.value

        # Remove accepted terms
        user.terms_of_use_accepted_version = None
        user.terms_of_use_version = None
        user.is_terms_of_use_accepted = False

        user.save()

        # Remove user from account_holders group
        KeycloakService.remove_from_account_holders_group(user.keycloak_guid)

        current_app.logger.debug('<delete_user')