示例#1
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
        is_govm_user = token.get('loginSource', None) == 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)
示例#2
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()
示例#3
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)
示例#4
0
    def get_all_product_subscription(org_id, skip_auth=False, **kwargs):
        """Get a list of all products with their subscription details."""
        org = OrgModel.find_by_org_id(org_id)
        user_from_context: UserContext = kwargs['user']
        if not org:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        # Check authorization for the user
        if not skip_auth:
            check_auth(user_from_context.token_info,
                       one_of_roles=(*CLIENT_ADMIN_ROLES, STAFF),
                       org_id=org_id)

        product_subscriptions: List[
            ProductSubscriptionModel] = ProductSubscriptionModel.find_by_org_id(
                org_id)
        subscriptions_dict = {
            x.product_code: x.status_code
            for x in product_subscriptions
        }

        products = Product.get_products(include_hidden=False)
        for product in products:
            product['subscriptionStatus'] = subscriptions_dict.get(
                product.get('code'),
                ProductSubscriptionStatus.NOT_SUBSCRIBED.value)

        return products
示例#5
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) from exception
示例#6
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)
示例#7
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)
示例#8
0
    def create_affiliation(org_id, business_identifier, pass_code=None):
        """Create an Affiliation."""
        # Validate if org_id is valid by calling Org Service.
        org = OrgService.find_by_org_id(org_id)
        if org is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        entity = EntityService.find_by_business_identifier(business_identifier)
        if entity is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        entity_id = entity.identifier

        authorized = True

        # Authorized if the entity has been claimed
        if entity.as_dict()['passCodeClaimed']:
            authorized = False

        # If a passcode was provided...
        if pass_code:
            # ... and the entity has a passcode on it, check that they match
            if entity.pass_code != pass_code:
                authorized = False
        # If a passcode was not provided...
        else:
            # ... check that the entity does not have a passcode protecting it
            if entity.pass_code:
                authorized = False

        if not authorized:
            # If org being affiliated was IMPLICIT, remove it since the affiliation was not valid
            if org.as_dict()['org_type'] == 'IMPLICIT':
                org.delete_org()
            raise BusinessException(Error.INVALID_USER_CREDENTIALS, None)

        # Ensure this affiliation does not already exist
        affiliation = AffiliationModel.find_affiliation_by_org_and_entity_ids(
            org_id, entity_id)
        if affiliation is not None:
            raise BusinessException(Error.DATA_ALREADY_EXISTS, None)

        affiliation = AffiliationModel(org_id=org_id, entity_id=entity_id)
        affiliation.save()
        entity.set_pass_code_claimed(True)

        return Affiliation(affiliation)
    def create_product_subscription(org_id,
                                    subscription_data: Tuple[Dict[str, Any]]):
        """Create product subscription for the user.

        create product subscription first
        create the product role next if roles are given
        """
        org = OrgModel.find_by_org_id(org_id)
        if not org:
            raise BusinessException(Error.DATA_NOT_FOUND, None)
        subscriptions_list = subscription_data.get('subscriptions')
        # just used for returning all the models.. not ideal..
        # todo remove this and may be return the subscriptions from db
        subscriptions_model_list = []
        for subscription in subscriptions_list:
            product_code = subscription.get('productCode')
            product = ProductCodeModel.find_by_code(product_code)
            if product:
                product_subscription = ProductSubscriptionModel(
                    org_id=org_id, product_code=product_code).save()
                subscriptions_model_list.append(product_subscription)
            else:
                raise BusinessException(Error.DATA_NOT_FOUND, None)
            if subscription.get('productRoles'):
                for role in subscription.get('productRoles'):
                    product_role_code = ProductRoleCodeModel.find_by_code_and_product_code(
                        role, product_code)
                    if product_role_code:
                        ProductSubscriptionRoleModel(
                            product_subscription_id=product_subscription.id,
                            product_role_id=product_role_code.id).save()
            else:  # empty product roles ;give subscription to everything
                product_roles = ProductRoleCodeModel.find_all_roles_by_product_code(
                    product_code)
                obj = []
                for role in product_roles:
                    obj.append(
                        ProductSubscriptionRoleModel(
                            product_subscription_id=product_subscription.id,
                            product_role_id=role.id))

                db.session.bulk_save_objects(obj)
                db.session.commit()

        # TODO return something better/useful.may be return the whole model from db
        return subscriptions_model_list
示例#10
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')
示例#11
0
    def send_admin_notification(user, url, recipient_email_list, org_name):
        """Send the admin email notification."""
        subject = '[BC Registries and Online Services] {} {} has responded for the invitation to join the account {}'. \
            format(user['firstname'], user['firstname'], org_name)
        sender = CONFIG.MAIL_FROM_ID
        try:
            template = ENV.get_template('email_templates/admin_notification_email.html')
        except Exception:
            raise BusinessException(Error.FAILED_INVITATION, None)

        sent_response = send_email(subject, sender, recipient_email_list,
                                   template.render(url=url, user=user, org_name=org_name,
                                                   logo_url=f'{url}/{CONFIG.REGISTRIES_LOGO_IMAGE_NAME}'))
        if not sent_response:
            # invitation.invitation_status_code = 'FAILED'
            # invitation.save()
            raise BusinessException(Error.FAILED_INVITATION, None)
示例#12
0
 def refresh_token(refresh_token):
     """Refresh user token."""
     try:
         response = KEYCLOAK_OPENID.refresh_token(refresh_token,
                                                  ['refresh_token'])
         return response
     except Exception as err:
         raise BusinessException(Error.INVALID_REFRESH_TOKEN, err)
示例#13
0
 def update_terms_of_use(is_terms_accepted, terms_of_use_version, **kwargs):
     """Update terms of use for an existing user."""
     current_app.logger.debug('update_terms_of_use')
     user_from_context: UserContext = kwargs['user_context']
     if user_from_context.token_info is None:
         raise BusinessException(Error.DATA_NOT_FOUND, None)
     user = UserModel.update_terms_of_use(is_terms_accepted, terms_of_use_version)
     return User(user)
示例#14
0
def test_get_codes_returns_exception(client, jwt, session):  # pylint:disable=unused-argument
    """Assert that the code type can not be fetched and with expcetion."""
    with patch.object(CodesService,
                      'fetch_codes',
                      side_effect=BusinessException(Error.UNDEFINED_ERROR,
                                                    None)):
        rv = client.get('/api/v1/codes/{}'.format('membership_type'),
                        content_type='application/json')
        assert rv.status_code == http_status.HTTP_400_BAD_REQUEST
示例#15
0
    def get_bcol_details(bcol_credential: Dict, org_info: Dict = None, bearer_token: str = None, org_id=None):
        """Retrieve and validate BC Online credentials."""
        bcol_response = None
        if bcol_credential:
            bcol_response = RestService.post(endpoint=current_app.config.get('BCOL_API_URL') + '/profiles',
                                             data=bcol_credential, token=bearer_token, raise_for_status=False)

            if bcol_response.status_code != http_status.HTTP_200_OK:
                error = json.loads(bcol_response.text)
                raise BusinessException(CustomException(error['detail'], bcol_response.status_code), None)

            bcol_account_number = bcol_response.json().get('accountNumber')
            if org_info:
                if bcol_response.json().get('orgName') != org_info.get('name'):
                    raise BusinessException(Error.INVALID_INPUT, None)
            if Org.bcol_account_link_check(bcol_account_number, org_id):
                raise BusinessException(Error.BCOL_ACCOUNT_ALREADY_LINKED, None)
        return bcol_response
示例#16
0
def test_add_org_invalid_returns_exception(client, jwt, session):  # pylint:disable=unused-argument
    """Assert that POSTing an invalid org returns an exception."""
    headers = factory_auth_header(jwt, claims=TestJwtClaims.public_user_role)
    rv = client.post('/api/v1/users', headers=headers, content_type='application/json')

    with patch.object(OrgService, 'create_org', side_effect=BusinessException(Error.DATA_ALREADY_EXISTS, None)):
        rv = client.post('/api/v1/orgs', data=json.dumps(TestOrgInfo.org1),
                         headers=headers, content_type='application/json')
        assert rv.status_code == 400
示例#17
0
    def search_orgs(**kwargs):  # pylint: disable=too-many-locals
        """Search for orgs based on input parameters."""
        orgs = {'orgs': []}
        if kwargs.get('business_identifier', None):
            affiliation: AffiliationModel = AffiliationModel. \
                find_affiliations_by_business_identifier(kwargs.get('business_identifier'))
            if affiliation:
                orgs['orgs'].append(
                    Org(OrgModel.find_by_org_id(affiliation.org_id)).as_dict())
        else:
            include_invitations: bool = False

            page: int = int(kwargs.get('page'))
            limit: int = int(kwargs.get('limit'))
            statuses: str = kwargs.get('statuses', None)
            name: str = kwargs.get('name', None)
            # https://github.com/bcgov/entity/issues/4786
            access_type, is_staff_admin = Org.refine_access_type(
                kwargs.get('access_type', None), kwargs.get('token', None))
            search_args = (access_type, name, statuses,
                           kwargs.get('bcol_account_id', None), page, limit)

            if statuses and OrgStatus.PENDING_ACTIVATION.value in statuses:
                # only staff admin can see director search accounts
                # https://github.com/bcgov/entity/issues/4786
                if not is_staff_admin:
                    raise BusinessException(Error.INVALID_USER_CREDENTIALS,
                                            None)
                org_models, total = OrgModel.search_pending_activation_orgs(
                    name)
                include_invitations = True
            else:
                org_models, total = OrgModel.search_org(*search_args)

            for org in org_models:
                org_dict = Org(org).as_dict()
                org_dict['contacts'] = []
                org_dict['invitations'] = []

                if org.contacts:
                    org_dict['contacts'].append(
                        ContactSchema(exclude=('links', )).dump(
                            org.contacts[0].contact, many=False))

                if include_invitations and org.invitations:
                    org_dict['invitations'].append(
                        InvitationSchema(exclude=('membership', )).dump(
                            org.invitations[0].invitation, many=False))

                orgs['orgs'].append(org_dict)

            orgs['total'] = total
            orgs['page'] = page
            orgs['limit'] = limit

        return orgs
示例#18
0
文件: user.py 项目: jeznorth/sbc-auth
    def delete_contact(token):
        """Delete the contact for an existing user."""
        current_app.logger.info('delete_contact')
        user = UserModel.find_by_jwt_token(token)
        if not user or not user.contacts:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        User.__delete_contact(user)

        return User(user)
示例#19
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)
示例#20
0
    def delete_affiliation(org_id, business_identifier):
        """Delete the affiliation for the provided org id and business id."""
        org = OrgService.find_by_org_id(org_id)
        if org is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        entity = EntityService.find_by_business_identifier(business_identifier)
        if entity is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        entity_id = entity.identifier

        affiliation = AffiliationModel.find_affiliation_by_org_and_entity_ids(
            org_id=org_id, entity_id=entity_id)
        if affiliation is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        affiliation.delete()
        entity.set_pass_code_claimed(False)
示例#21
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)
示例#22
0
 def delete_invitation(invitation_id, token_info: Dict = None):
     """Delete the specified invitation."""
     # Ensure that the current user is ADMIN or COORDINATOR for each org in the invitation
     invitation = InvitationModel.find_invitation_by_id(invitation_id)
     if invitation is None:
         raise BusinessException(Error.DATA_NOT_FOUND, None)
     for membership in invitation.membership:
         org_id = membership.org_id
         check_auth(token_info, org_id=org_id, one_of_roles=(ADMIN, COORDINATOR, STAFF))
     invitation.delete()
示例#23
0
    def update_membership(self, updated_fields, token_info: Dict = None):
        """Update an existing membership with the given role."""
        # Ensure that this user is an COORDINATOR or ADMIN on the org associated with this membership
        current_app.logger.debug('<update_membership')
        check_auth(org_id=self._model.org_id,
                   token_info=token_info,
                   one_of_roles=(COORDINATOR, ADMIN, STAFF))

        # bceid Members cant be ADMIN's.Unless they have an affidavit approved.
        # TODO when multiple teams for bceid are present , do if the user has affidavit present check
        is_bceid_user = self._model.user.login_source == LoginSource.BCEID.value
        if is_bceid_user and getattr(
                updated_fields.get('membership_type', None), 'code',
                None) == ADMIN:
            raise BusinessException(Error.BCEID_USERS_CANT_BE_OWNERS, None)

        # Ensure that a member does not upgrade a member to ADMIN from COORDINATOR unless they are an ADMIN themselves
        if self._model.membership_type.code == COORDINATOR and updated_fields.get(
                'membership_type', None) == ADMIN:
            check_auth(org_id=self._model.org_id,
                       token_info=token_info,
                       one_of_roles=(ADMIN, STAFF))

        # No one can change an ADMIN's status, only option is ADMIN to leave the team. #2319
        if updated_fields.get('membership_status', None) \
                and updated_fields['membership_status'].id == Status.INACTIVE.value \
                and self._model.membership_type.code == ADMIN:
            raise BusinessException(Error.OWNER_CANNOT_BE_REMOVED, None)

        # Ensure that if downgrading from owner that there is at least one other owner in org
        if self._model.membership_type.code == ADMIN and \
                updated_fields.get('membership_type', None) != ADMIN and \
                OrgService(self._model.org).get_owner_count() == 1:
            raise BusinessException(Error.CHANGE_ROLE_FAILED_ONLY_OWNER, None)

        for key, value in updated_fields.items():
            if value is not None:
                setattr(self._model, key, value)
        self._model.save()
        # Add to account_holders group in keycloak
        Membership._add_or_remove_group(self._model)
        current_app.logger.debug('>update_membership')
        return self
示例#24
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 and 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 and Online Services] Welcome to the account {}'. \
                format(org_name)
            # TODO how to check properly if user is bceid user
            is_bceid_user = self._model.user.username.find('@bceid') > 0
            if is_bceid_user:
                template_name = 'membership_approved_notification_email_for_bceid.html'
            else:
                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)

        try:
            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:
                current_app.logger.error('<send_notification_to_member failed')
                raise BusinessException(Error.FAILED_NOTIFICATION, None)
        except:  # noqa=B901
            current_app.logger.error('<send_notification_to_member failed')
            raise BusinessException(Error.FAILED_NOTIFICATION, None)
示例#25
0
 def validate_access_type(is_bceid_user, is_staff_admin, org_info):
     """Validate and return access type."""
     access_type: str = org_info.get('accessType', None)
     if access_type:
         if not is_staff_admin and access_type == AccessType.ANONYMOUS.value:
             raise BusinessException(Error.USER_CANT_CREATE_ANONYMOUS_ORG, None)
         if not is_bceid_user and access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value):
             raise BusinessException(Error.USER_CANT_CREATE_EXTRA_PROVINCIAL_ORG, None)
         if is_bceid_user and access_type not in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value):
             raise BusinessException(Error.USER_CANT_CREATE_REGULAR_ORG, None)
     else:
         # If access type is not provided, add default value based on user
         if is_staff_admin:
             access_type = AccessType.ANONYMOUS.value
         elif is_bceid_user:
             access_type = AccessType.EXTRA_PROVINCIAL.value
         else:
             access_type = AccessType.REGULAR.value
     return access_type
示例#26
0
    def _get_nr_details(nr_number: str, token: str):
        """Return NR details by calling legal-api."""
        get_nr_url = current_app.config.get('LEGAL_API_URL') + f'/nameRequests/{nr_number}'
        try:
            get_nr_response = RestService.get(get_nr_url, token=token)
        except (HTTPError, ServiceUnavailableException) as e:
            current_app.logger.info(e)
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        return get_nr_response.json()
示例#27
0
    def update_contact(org_id, contact_info):
        """Update the existing contact for this org."""
        current_app.logger.debug('>update_contact ')
        org = OrgModel.find_by_org_id(org_id)
        if org is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        # find the contact link for this org
        contact_link = ContactLinkModel.find_by_org_id(org_id)
        if contact_link is None or contact_link.contact is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        contact = contact_link.contact
        contact.update_from_dict(**camelback2snake(contact_info))
        contact.save()
        current_app.logger.debug('<update_contact ')

        # return the updated contact
        return ContactService(contact)
示例#28
0
    def get_login_options_for_org(org_id, allowed_roles: Tuple = None):
        """Get the payment settings for the given org."""
        current_app.logger.debug('get_login_options(>')
        org = OrgModel.find_by_org_id(org_id)
        if org is None:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        # Check authorization for the user
        check_auth(one_of_roles=allowed_roles, org_id=org_id)
        return AccountLoginOptionsModel.find_active_by_org_id(org_id)
示例#29
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)
示例#30
0
    def delete_contact(org_id):
        """Delete the contact for this org."""
        current_app.logger.debug('>delete_contact ')
        org = OrgModel.find_by_org_id(org_id)
        if not org or not org.contacts:
            raise BusinessException(Error.DATA_NOT_FOUND, None)

        deleted_contact = Org.__delete_contact(org)
        current_app.logger.debug('<delete_contact ')

        return ContactService(deleted_contact)