Exemplo n.º 1
0
    def delete_user():
        """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()
        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')
Exemplo n.º 2
0
    def send_notification_to_member(self, origin_url, notification_type):
        """Send member notification."""
        current_app.logger.debug(f'<send {notification_type} notification')
        org_name = self._model.org.name
        template_name = ''
        params = {}
        if notification_type == NotificationType.ROLE_CHANGED.value:
            subject = '[BC Registries & Online Services] Your Role has been changed'
            template_name = 'role_changed_notification_email.html'
            params = {'org_name': org_name, 'role': self._model.membership_type.code,
                      'label': self._model.membership_type.label}
        elif notification_type == NotificationType.MEMBERSHIP_APPROVED.value:
            subject = '[BC Registries & Online Services] Welcome to the team {}'. \
                format(org_name)
            template_name = 'membership_approved_notification_email.html'
            params = {'org_name': org_name}
        sender = CONFIG.MAIL_FROM_ID
        template = ENV.get_template(f'email_templates/{template_name}')
        context_path = CONFIG.AUTH_WEB_TOKEN_CONFIRM_PATH
        app_url = '{}/{}'.format(origin_url, context_path)

        sent_response = send_email(subject, sender, self._model.user.contacts[0].contact.email,
                                   template.render(url=app_url, params=params,
                                                   logo_url=f'{app_url}/{CONFIG.REGISTRIES_LOGO_IMAGE_NAME}'))
        current_app.logger.debug('<send_approval_notification_to_member')
        if not sent_response:
            # invitation.invitation_status_code = 'FAILED'
            # invitation.save()
            current_app.logger.error('<send_notification_to_member failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None)
Exemplo n.º 3
0
    def send_approved_rejected_notification(receipt_admin_email, org_name,
                                            org_id, org_status: OrgStatus,
                                            origin_url):
        """Send Approved/Rejected notification to the user."""
        current_app.logger.debug('<send_approved_rejected_notification')

        if org_status == OrgStatus.ACTIVE.value:
            notification_type = 'nonbcscOrgApprovedNotification'
        elif org_status == OrgStatus.REJECTED.value:
            notification_type = 'nonbcscOrgRejectedNotification'
        else:
            return  # Don't send mail for any other status change
        app_url = f"{origin_url}/{current_app.config.get('AUTH_WEB_TOKEN_CONFIRM_PATH')}"
        data = {
            'accountId': org_id,
            'emailAddresses': receipt_admin_email,
            'contextUrl': app_url,
            'orgName': org_name
        }
        try:
            publish_to_mailer(notification_type, org_id=org_id, data=data)
            current_app.logger.debug('<send_approved_rejected_notification')
        except Exception as e:  # noqa=B901
            current_app.logger.error(
                '<send_approved_rejected_notification failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None) from e
Exemplo n.º 4
0
    def search_orgs(search: OrgSearch):  # pylint: disable=too-many-locals
        """Search for orgs based on input parameters."""
        orgs_result = {
            'orgs': [],
            'page': search.page,
            'limit': search.limit,
            'total': 0
        }
        include_invitations: bool = False
        search.access_type, is_staff_admin = Org.refine_access_type(
            search.access_type)
        if search.statuses and OrgStatus.PENDING_ACTIVATION.value in search.statuses:
            # only staff admin can see director search accounts
            if not is_staff_admin:
                raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)
            org_models, orgs_result[
                'total'] = OrgModel.search_pending_activation_orgs(
                    name=search.name)
            include_invitations = True
        else:
            org_models, orgs_result['total'] = OrgModel.search_org(search)

        for org in org_models:
            orgs_result['orgs'].append({
                **Org(org).as_dict(),
                'contacts': [
                    ContactSchema(exclude=('links', )).dump(
                        org.contacts[0].contact, many=False)
                ] if org.contacts else [],
                'invitations': [
                    InvitationSchema(exclude=('membership', )).dump(
                        org.invitations[0].invitation, many=False)
                ] if include_invitations and org.invitations else [],
            })
        return orgs_result
Exemplo n.º 5
0
 def get_bcol_details(bcol_credential: Dict, org_id=None):
     """Retrieve and validate BC Online credentials."""
     arg_dict = {'bcol_credential': bcol_credential, 'org_id': org_id}
     validator_obj = bcol_credentials_validate(**arg_dict)
     if not validator_obj.is_valid:
         raise BusinessException(validator_obj.error[0], None)
     return validator_obj.info.get('bcol_response', None)
Exemplo n.º 6
0
    def create_invitation(invitation_info: Dict, user, token_info: Dict, invitation_origin):
        """Create a new invitation."""
        # Ensure that the current user is ADMIN or COORDINATOR on each org being invited to
        context_path = CONFIG.AUTH_WEB_TOKEN_CONFIRM_PATH
        org_id = invitation_info['membership'][0]['orgId']
        # get the org and check the access_type
        org = OrgModel.find_by_org_id(org_id)
        if not org:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        check_auth(token_info, org_id=org_id, one_of_roles=(ADMIN, COORDINATOR, STAFF))

        org_name = org.name
        invitation_type = InvitationType.DIRECTOR_SEARCH.value if org.access_type == AccessType.ANONYMOUS.value \
            else InvitationType.STANDARD.value
        if org.access_type == AccessType.ANONYMOUS.value:  # anonymous account never get bceid or bcsc choices
            mandatory_login_source = LoginSource.BCROS.value
        else:
            default_login_option_based_on_accesstype = LoginSource.BCSC.value if \
                org.access_type == AccessType.REGULAR.value else LoginSource.BCEID.value
            role = invitation_info['membership'][0]['membershipType']
            account_login_options = AccountLoginOptionsModel.find_active_by_org_id(org.id)
            mandatory_login_source = LoginSource.BCSC.value if \
                role == ADMIN else getattr(account_login_options, 'login_source',
                                           default_login_option_based_on_accesstype)

        invitation = InvitationModel.create_from_dict(invitation_info, user.identifier, invitation_type)
        confirmation_token = Invitation.generate_confirmation_token(invitation.id, invitation.type)
        invitation.token = confirmation_token
        invitation.login_source = mandatory_login_source
        invitation.save()
        Invitation.send_invitation(invitation, org_name, user.as_dict(),
                                   '{}/{}'.format(invitation_origin, context_path), mandatory_login_source)
        return Invitation(invitation)
Exemplo n.º 7
0
def test_add_entity_invalid_returns_exception(client, jwt, session):  # pylint:disable=unused-argument
    """Assert that POSTing an invalid entity returns an exception."""
    headers = factory_auth_header(jwt, claims=TestJwtClaims.system_role)
    with patch.object(EntityService, 'save_entity', side_effect=BusinessException(Error.DATA_ALREADY_EXISTS, None)):
        rv = client.post('/api/v1/entities', data=json.dumps(TestEntityInfo.entity1),
                         headers=headers, content_type='application/json')
        assert rv.status_code == 400
Exemplo n.º 8
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 == ADMIN:
                 is_user_an_owner = True
         elif member.membership_type_code == ADMIN:
             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()
Exemplo n.º 9
0
    def find_by_jwt_token(cls, **kwargs):
        """Find user from database by user token."""
        user_from_context: UserContext = kwargs['user_context']
        if not user_from_context.token_info:
            return None

        user_model = UserModel.find_by_jwt_token()

        if not user_model:
            if kwargs.get('silent_mode', False):
                return None
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        is_anonymous_user = user_from_context.token_info.get('accessType', None) == AccessType.ANONYMOUS.value
        is_govm_user = user_from_context.login_source == LoginSource.STAFF.value
        # If terms accepted , double check if there is a new TOS in place. If so, update the flag to false.
        if user_model.is_terms_of_use_accepted:
            if is_anonymous_user:
                document_type = DocumentType.TERMS_OF_USE_DIRECTOR_SEARCH.value
            elif is_govm_user:
                document_type = DocumentType.TERMS_OF_USE_GOVM.value
            else:
                document_type = DocumentType.TERMS_OF_USE.value
            # get the digit version of the terms of service..ie d1 gives 1 ; d2 gives 2..for proper comparison
            latest_version = util.digitify(DocumentService.find_latest_version_by_type(document_type))
            current_version = util.digitify(user_model.terms_of_use_accepted_version)
            if latest_version > current_version:
                user_model.is_terms_of_use_accepted = False

        return User(user_model)
Exemplo n.º 10
0
    def send_staff_review_account_reminder(user, org_id, origin_url):
        """Send staff review account reminder notification."""
        current_app.logger.debug('<send_staff_review_account_reminder')
        recipient = current_app.config.get('STAFF_ADMIN_EMAIL')
        context_path = f'review-account/{org_id}'
        app_url = '{}/{}'.format(
            origin_url, current_app.config.get('AUTH_WEB_TOKEN_CONFIRM_PATH'))
        review_url = '{}/{}'.format(app_url, context_path)
        first_name = ''
        last_name = ''

        if user:
            first_name = user.firstname
            last_name = user.lastname

        data = {
            'accountId': org_id,
            'emailAddresses': recipient,
            'contextUrl': review_url,
            'userFirstName': first_name,
            'userLastName': last_name
        }
        try:
            publish_to_mailer('staffReviewAccount', org_id=org_id, data=data)
            current_app.logger.debug('<send_staff_review_account_reminder')
        except:  # noqa=B901
            current_app.logger.error(
                '<send_staff_review_account_reminder failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None)
Exemplo n.º 11
0
    def _validate_and_get_payment_method(selected_payment_type: str,
                                         org_type: OrgType,
                                         access_type=None) -> str:

        # TODO whats a  better place for this
        org_payment_method_mapping = {
            OrgType.BASIC:
            (PaymentMethod.CREDIT_CARD.value, PaymentMethod.DIRECT_PAY.value,
             PaymentMethod.ONLINE_BANKING.value),
            OrgType.PREMIUM:
            (PaymentMethod.CREDIT_CARD.value, PaymentMethod.DIRECT_PAY.value,
             PaymentMethod.PAD.value, PaymentMethod.BCOL.value)
        }
        if access_type == AccessType.GOVM.value:
            payment_type = PaymentMethod.EJV.value
        elif selected_payment_type:
            valid_types = org_payment_method_mapping.get(org_type, [])
            if selected_payment_type in valid_types:
                payment_type = selected_payment_type
            else:
                raise BusinessException(Error.INVALID_INPUT, None)
        else:
            payment_type = PaymentMethod.BCOL.value if \
                org_type == OrgType.PREMIUM else Org._get_default_payment_method_for_creditcard()
        return payment_type
Exemplo n.º 12
0
    def update_entity(business_identifier: str, entity_info: dict, **kwargs):
        """Update an entity from the given dictionary.

        Completely replaces the entity including the business identifier
        """
        if not entity_info or not business_identifier:
            return None
        user_from_context: UserContext = kwargs['user_context']
        # todo No memberhsip created at this point. check_auth wont work.ideally we shud put the logic in here
        # check_auth(token_info, one_of_roles=allowed_roles, business_identifier=business_identifier)
        entity = EntityModel.find_by_business_identifier(business_identifier)
        if entity is None or entity.corp_type_code is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        # if entity.corp_type_code != token_info.get('corp_type', None):
        #    raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)

        if user_from_context.is_system():
            if entity_info.get('passCode') is not None:
                entity_info['passCode'] = passcode_hash(entity_info['passCode'])

        # Small mapping from state -> status. EX in LEAR: Business.State.HISTORICAL
        if 'state' in entity_info:
            entity_info['status'] = entity_info['state']
            del entity_info['state']

        entity.update_from_dict(**camelback2snake(entity_info))
        entity.commit()

        entity = Entity(entity)
        return entity
Exemplo n.º 13
0
    def create_affidavit(token_info: Dict, affidavit_info: Dict):
        """Create a new affidavit record."""
        current_app.logger.debug('<create_affidavit ')
        user = UserService.find_by_jwt_token(token=token_info)
        # If the user already have a pending affidavit, raise error
        existing_affidavit = AffidavitModel.find_pending_by_user_id(
            user_id=user.identifier)
        if existing_affidavit is not None:
            raise BusinessException(Error.ACTIVE_AFFIDAVIT_EXISTS, None)

        contact = affidavit_info.pop('contact')
        affidavit_model = AffidavitModel(
            issuer=affidavit_info.get('issuer'),
            document_id=affidavit_info.get('documentId'),
            status_code=AffidavitStatus.PENDING.value,
            user_id=user.identifier)
        affidavit_model.add_to_session()

        # Save contact for the affidavit
        if contact:
            contact = ContactModel(**camelback2snake(contact))
            contact.add_to_session()

            contact_link = ContactLinkModel()
            contact_link.affidavit = affidavit_model
            contact_link.contact = contact
            contact_link.add_to_session()

        affidavit_model.save()

        return Affidavit(affidavit_model)
Exemplo n.º 14
0
    def update_org(
            self,
            org_info,
            token_info: Dict = None,  # pylint: disable=too-many-locals
            bearer_token: str = None):
        """Update the passed organization with the new info."""
        current_app.logger.debug('<update_org ')

        has_org_updates: bool = False  # update the org table if this variable is set true

        is_name_getting_updated = 'name' in org_info
        if is_name_getting_updated:
            existing_similar__org = OrgModel.find_similar_org_by_name(
                org_info['name'], self._model.id)
            if existing_similar__org is not None:
                raise BusinessException(Error.DATA_CONFLICT, None)
            has_org_updates = True

        # If the account is created using BCOL credential, verify its valid bc online account
        # If it's a valid account disable the current one and add a new one
        if bcol_credential := org_info.pop('bcOnlineCredential', None):
            bcol_response = Org.get_bcol_details(bcol_credential, bearer_token,
                                                 self._model.id).json()
            Org._map_response_to_org(bcol_response, org_info)
            has_org_updates = True
Exemplo n.º 15
0
 def logout(refresh_token):
     """Logout user by refresh-token."""
     try:
         response = KEYCLOAK_OPENID.logout(refresh_token)
         return response
     except Exception as err:
         raise BusinessException(Error.INVALID_REFRESH_TOKEN, err)
Exemplo n.º 16
0
    def find_by_jwt_token(cls, token: dict = None):
        """Find user from database by user token."""
        if not token:
            return None

        user_model = UserModel.find_by_jwt_token(token)

        if not user_model:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        is_anonymous_user = token.get('accessType',
                                      None) == AccessType.ANONYMOUS.value
        # If terms accepted , double check if there is a new TOS in place. If so, update the flag to false.
        if user_model.is_terms_of_use_accepted:
            document_type = DocumentType.TERMS_OF_USE_DIRECTOR_SEARCH.value if is_anonymous_user \
                else DocumentType.TERMS_OF_USE.value
            # get the digit version of the terms of service..ie d1 gives 1 ; d2 gives 2..for proper comparison
            latest_version = util.digitify(
                DocumentService.find_latest_version_by_type(document_type))
            current_version = util.digitify(
                user_model.terms_of_use_accepted_version)
            if latest_version > current_version:
                user_model.is_terms_of_use_accepted = False

        return User(user_model)
Exemplo n.º 17
0
 def get_user_by_username(username):
     """Get user from Keycloak by username."""
     try:
         # Get user id
         user_id_keycloak = KEYCLOAK_ADMIN.get_user_id(username)
     except Exception as err:
         raise BusinessException(Error.UNDEFINED_ERROR, err)
     # Get User
     if user_id_keycloak is not None:
         try:
             user = KEYCLOAK_ADMIN.get_user(user_id_keycloak)
             return user
         except Exception as err:
             raise BusinessException(Error.UNDEFINED_ERROR, err)
     else:
         raise BusinessException(Error.DATA_NOT_FOUND, None)
Exemplo n.º 18
0
 def update_terms_of_use(token, is_terms_accepted, terms_of_use_version):
     """Update terms of use for an existing user."""
     current_app.logger.debug('update_terms_of_use')
     if token is None:
         raise BusinessException(Error.DATA_NOT_FOUND, None)
     user = UserModel.update_terms_of_use(token, is_terms_accepted, terms_of_use_version)
     return User(user)
Exemplo n.º 19
0
    def send_invitation(invitation: InvitationModel, org_name, user, app_url):
        """Send the email notification."""
        current_app.logger.debug('<send_invitation')
        mail_configs = Invitation.get_invitation_configs(
            invitation.type, org_name)
        subject = mail_configs.get('subject').format(user['firstname'],
                                                     user['lastname'])
        sender = CONFIG.MAIL_FROM_ID
        recipient = invitation.recipient_email
        token_confirm_url = '{}/{}/{}'.format(
            app_url, mail_configs.get('token_confirm_path'), invitation.token)
        template = ENV.get_template(
            f"email_templates/{mail_configs.get('template_name')}.html")

        sent_response = send_email(
            subject, sender, recipient,
            template.render(
                invitation=invitation,
                url=token_confirm_url,
                user=user,
                org_name=org_name,
                logo_url=f'{app_url}/{CONFIG.REGISTRIES_LOGO_IMAGE_NAME}'))
        if not sent_response:
            invitation.invitation_status_code = 'FAILED'
            invitation.save()
            current_app.logger.debug('>send_invitation failed')
            raise BusinessException(Error.FAILED_INVITATION, None)
        current_app.logger.debug('>send_invitation')
Exemplo n.º 20
0
    def fetch_codes(cls, code_type: str = None) -> []:
        """Return values from code table."""
        try:
            data: [] = None
            if code_type:
                code_model = Codes.fetch_data_model(code_type.lower())

                if code_model:
                    codes = code_model.query.all()

                    data = []
                    # transform each of entry to a dictionary base on schema.
                    for entry in codes:
                        module_name = f'auth_api.schemas.{entry.__tablename__}'
                        class_name = f'{entry.__class__.__name__}Schema'
                        try:
                            schema = getattr(
                                importlib.import_module(module_name),
                                class_name)
                        except ModuleNotFoundError:
                            schema = getattr(
                                importlib.import_module(
                                    'auth_api.schemas.basecode_type'),
                                'BaseCodeSchema')
                        code_schema = schema()
                        data.append(code_schema.dump(entry, many=False))
                return data
            return None
        except Exception as exception:  # NOQA # pylint: disable=broad-except
            raise BusinessException(Error.UNDEFINED_ERROR, exception)
Exemplo n.º 21
0
    def update_user(user: KeycloakUser):
        """Add user to Keycloak."""
        config = current_app.config
        # Add user and set password
        admin_token = KeycloakService._get_admin_token(upstream=True)

        base_url = config.get('KEYCLOAK_BCROS_BASE_URL')
        realm = config.get('KEYCLOAK_BCROS_REALMNAME')

        existing_user = KeycloakService.get_user_by_username(
            user.user_name, admin_token=admin_token)
        if not existing_user:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        headers = {
            'Content-Type': ContentType.JSON.value,
            'Authorization': f'Bearer {admin_token}'
        }

        update_user_url = f'{base_url}/auth/admin/realms/{realm}/users/{existing_user.id}'
        response = requests.put(update_user_url,
                                data=user.value(),
                                headers=headers)
        response.raise_for_status()

        return KeycloakService.get_user_by_username(user.user_name,
                                                    admin_token)
Exemplo n.º 22
0
    def send_invitation(invitation: InvitationModel, org_name, user, app_url):
        """Send the email notification."""
        current_app.logger.debug('<send_invitation')
        subject = '[BC Registries & Online Services] {} {} has invited you to join a team'.format(
            user['firstname'], user['lastname'])
        sender = CONFIG.MAIL_FROM_ID
        recipient = invitation.recipient_email
        token_confirm_url = '{}/validatetoken/{}'.format(
            app_url, invitation.token)
        template = ENV.get_template(
            'email_templates/business_invitation_email.html')

        sent_response = send_email(
            subject, sender, recipient,
            template.render(
                invitation=invitation,
                url=token_confirm_url,
                user=user,
                org_name=org_name,
                logo_url=f'{app_url}/{CONFIG.REGISTRIES_LOGO_IMAGE_NAME}'))
        if not sent_response:
            invitation.invitation_status_code = 'FAILED'
            invitation.save()
            current_app.logger.debug('>send_invitation failed')
            raise BusinessException(Error.FAILED_INVITATION, None)
        current_app.logger.debug('>send_invitation')
Exemplo n.º 23
0
    def add_user(user: KeycloakUser, return_if_exists: bool = False, throw_error_if_exists: bool = False):
        """Add user to Keycloak."""
        config = current_app.config
        # Add user and set password
        admin_token = KeycloakService._get_admin_token(upstream=True)

        base_url = config.get('KEYCLOAK_BCROS_BASE_URL')
        realm = config.get('KEYCLOAK_BCROS_REALMNAME')

        # Check if the user exists
        if return_if_exists or throw_error_if_exists:
            existing_user = KeycloakService.get_user_by_username(user.user_name, admin_token=admin_token)
            if existing_user:
                if not throw_error_if_exists:
                    return existing_user
                raise BusinessException(Error.USER_ALREADY_EXISTS_IN_KEYCLOAK, None)
        # Add user to the keycloak group '$group_name'
        headers = {
            'Content-Type': ContentType.JSON.value,
            'Authorization': f'Bearer {admin_token}'
        }

        add_user_url = f'{base_url}/auth/admin/realms/{realm}/users'
        response = requests.post(add_user_url, data=user.value(), headers=headers)
        response.raise_for_status()

        return KeycloakService.get_user_by_username(user.user_name, admin_token)
Exemplo n.º 24
0
    def _notify_admin_about_hold(task_model, org: OrgModel = None, is_new_bceid_admin_request: bool = False,
                                 membership_id: int = None, user: UserModel = None):
        if is_new_bceid_admin_request:
            create_account_signin_route = urllib.parse.quote_plus(
                f"{current_app.config.get('BCEID_ADMIN_SETUP_ROUTE')}/"
                f'{task_model.account_id}/'
                f'{membership_id}')
            admin_email = user.contacts[0].contact.email
            account_id = task_model.account_id
            mailer_type = 'resubmitBceidAdmin'

        else:
            create_account_signin_route = urllib.parse. \
                quote_plus(f"{current_app.config.get('BCEID_ACCOUNT_SETUP_ROUTE')}/"
                           f'{org.id}')
            admin_email = ContactLinkModel.find_by_user_id(org.members[0].user.id).contact.email
            account_id = org.id
            mailer_type = 'resubmitBceidOrg'

        data = {
            'remarks': task_model.remarks,
            'applicationDate': f"{task_model.created.strftime('%m/%d/%Y')}",
            'accountId': account_id,
            'emailAddresses': admin_email,
            'contextUrl': f"{current_app.config.get('WEB_APP_URL')}"
                          f"/{current_app.config.get('BCEID_SIGNIN_ROUTE')}/"
                          f'{create_account_signin_route}'
        }
        try:
            publish_to_mailer(mailer_type, org_id=account_id, data=data)
            current_app.logger.debug('<send_approval_notification_to_member')
        except Exception as e:  # noqa=B901
            current_app.logger.error('<send_notification_to_member failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None) from e
Exemplo n.º 25
0
    def update_login_option(org_id, login_source):
        """Create a new contact for this org."""
        # check for existing contact (only one contact per org for now)
        current_app.logger.debug('>update_login_option')
        org = OrgModel.find_by_org_id(org_id)
        if org is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        check_auth(one_of_roles=ADMIN, org_id=org_id)

        existing_login_option = AccountLoginOptionsModel.find_active_by_org_id(
            org_id)
        if existing_login_option is not None:
            existing_login_option.is_active = False
            existing_login_option.add_to_session()

        login_option = AccountLoginOptionsModel(login_source=login_source,
                                                org_id=org_id)
        login_option.save()
        ActivityLogPublisher.publish_activity(
            Activity(org_id,
                     ActivityAction.AUTHENTICATION_METHOD_CHANGE.value,
                     name=org.name,
                     value=login_source,
                     id=login_option.id))
        return login_option
Exemplo n.º 26
0
 def delete_user_by_username(username):
     """Delete user from Keycloak by username."""
     try:
         # Get user id
         user_id_keycloak = KEYCLOAK_ADMIN.get_user_id(username)
     except Exception as err:
         raise BusinessException(Error.UNDEFINED_ERROR, err)
     # Delete User
     if user_id_keycloak is not None:
         try:
             response = KEYCLOAK_ADMIN.delete_user(user_id_keycloak)
             return response
         except Exception as err:
             raise BusinessException(Error.UNDEFINED_ERROR, err)
     else:
         raise BusinessException(Error.DATA_NOT_FOUND, None)
Exemplo n.º 27
0
    def send_staff_review_account_reminder(
            relationship_id,
            task_relationship_type=TaskRelationshipType.ORG.value):
        """Send staff review account reminder notification."""
        current_app.logger.debug('<send_staff_review_account_reminder')
        user: UserModel = UserModel.find_by_jwt_token()
        recipient = current_app.config.get('STAFF_ADMIN_EMAIL')
        # Get task id that is related with the task. Task Relationship Type can be ORG, PRODUCT etc.
        task = TaskModel.find_by_task_relationship_id(
            task_relationship_type=task_relationship_type,
            relationship_id=relationship_id)
        context_path = f'review-account/{task.id}'
        app_url = f"{g.get('origin_url', '')}/{current_app.config.get('AUTH_WEB_TOKEN_CONFIRM_PATH')}"
        review_url = f'{app_url}/{context_path}'
        first_name = user.firstname
        last_name = user.lastname

        data = {
            'emailAddresses': recipient,
            'contextUrl': review_url,
            'userFirstName': first_name,
            'userLastName': last_name
        }
        try:
            publish_to_mailer('staffReviewAccount',
                              org_id=relationship_id,
                              data=data)
            current_app.logger.debug('<send_staff_review_account_reminder')
        except Exception as e:  # noqa=B901
            current_app.logger.error(
                '<send_staff_review_account_reminder failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None) from e
Exemplo n.º 28
0
 def get_token(username, password):
     """Get user access token by username and password."""
     try:
         response = KEYCLOAK_OPENID.token(username, password)
         return response
     except Exception as err:
         raise BusinessException(Error.INVALID_USER_CREDENTIALS, err)
Exemplo n.º 29
0
    def update_entity(business_identifier: str,
                      entity_info: dict,
                      token_info: Dict = None):
        """Update an entity from the given dictionary.

        Completely replaces the entity including the business identifier
        """
        if not entity_info or not business_identifier:
            return None
        # todo No memberhsip created at this point. check_auth wont work.ideally we shud put the logic in here
        # check_auth(token_info, one_of_roles=allowed_roles, business_identifier=business_identifier)
        entity = EntityModel.find_by_business_identifier(business_identifier)
        if entity is None or entity.corp_type_code is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        # if entity.corp_type_code != token_info.get('corp_type', None):
        #    raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)

        is_system = token_info and Role.SYSTEM.value in token_info.get(
            'realm_access').get('roles')
        if is_system:
            if entity_info.get('passCode') is not None:
                entity_info['passCode'] = passcode_hash(
                    entity_info['passCode'])

        entity.update_from_dict(**camelback2snake(entity_info))
        entity.commit()

        entity = Entity(entity)
        return entity
Exemplo n.º 30
0
def validate(is_fatal=False, **kwargs) -> ValidatorResponse:
    """Validate and return correct access type."""
    selected_payment_method: str = kwargs.get('selected_payment_method')
    access_type: str = kwargs.get('access_type')
    org_type: str = kwargs.get('org_type')
    default_cc_method = PaymentMethod.DIRECT_PAY.value if current_app.config.get(
        'DIRECT_PAY_ENABLED') else PaymentMethod.CREDIT_CARD.value
    validator_response = ValidatorResponse()
    org_payment_method_mapping = {
        OrgType.BASIC: (
            PaymentMethod.CREDIT_CARD.value, PaymentMethod.DIRECT_PAY.value, PaymentMethod.ONLINE_BANKING.value),
        OrgType.PREMIUM: (
            PaymentMethod.CREDIT_CARD.value, PaymentMethod.DIRECT_PAY.value,
            PaymentMethod.PAD.value, PaymentMethod.BCOL.value)
    }
    if access_type == AccessType.GOVM.value:
        payment_type = PaymentMethod.EJV.value
    elif selected_payment_method:
        valid_types = org_payment_method_mapping.get(org_type, [])
        if selected_payment_method in valid_types:
            payment_type = selected_payment_method
        else:
            validator_response.add_error(
                Error.INVALID_INPUT)
            if is_fatal:
                raise BusinessException(Error.INVALID_INPUT, None)
    else:
        payment_type = PaymentMethod.BCOL.value if \
            org_type == OrgType.PREMIUM else default_cc_method
    validator_response.add_info({'payment_type': payment_type})
    return validator_response