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
def test_delete_contact_user_link(session, auth_mock, keycloak_mock): # pylint:disable=unused-argument """Assert that a contact can not be deleted if contact link exists.""" user_with_token = TestUserInfo.user_test user_with_token['keycloak_guid'] = TestJwtClaims.edit_role['sub'] user_model = factory_user_model(user_info=user_with_token) user = UserService(user_model) org = OrgService.create_org(TestOrgInfo.org1, user_id=user.identifier) org_dictionary = org.as_dict() org_id = org_dictionary['id'] contact = factory_contact_model() contact_link = ContactLinkModel() contact_link.contact = contact contact_link.user = user_model contact_link.org = org._model # pylint:disable=protected-access contact_link = contact_link.flush() contact_link.commit() deleted_contact = UserService.delete_contact(TestJwtClaims.edit_role) assert deleted_contact is None delete_contact_link = ContactLinkModel.find_by_user_id(user.identifier) assert not delete_contact_link exist_contact_link = ContactLinkModel.find_by_org_id(org_id) assert exist_contact_link
def test_delete_contact_user_link(session, auth_mock): # pylint:disable=unused-argument """Assert that a contact can not be deleted if contact link exists.""" user_model = factory_user_model(user_info=TestUserInfo.user_test) user = UserService(user_model) org = OrgService.create_org(TestOrgInfo.org1, user_id=user.identifier) org_dictionary = org.as_dict() org_id = org_dictionary['id'] contact = factory_contact_model() contact_link = ContactLinkModel() contact_link.contact = contact contact_link.user = user_model contact_link.org = org._model # pylint:disable=protected-access contact_link.commit() updated_user = user.delete_contact(TestJwtClaims.user_test) dictionary = None dictionary = updated_user.as_dict() assert len(dictionary['contacts']) == 0 delete_contact_link = ContactLinkModel.find_by_user_id(user.identifier) assert not delete_contact_link exist_contact_link = ContactLinkModel.find_by_org_id(org_id) assert exist_contact_link
def add_contact(token, contact_info: dict, throw_error_for_duplicates: bool = True): """Add contact information for an existing user.""" current_app.logger.debug('add_contact') user = UserModel.find_by_jwt_token(token) if user is None: raise BusinessException(Error.DATA_NOT_FOUND, None) # check for existing contact (we only want one contact per user) contact_link = ContactLinkModel.find_by_user_id(user.id) if contact_link is not None: if not throw_error_for_duplicates: # TODO may be throw whole object return None raise BusinessException(Error.DATA_ALREADY_EXISTS, None) contact = ContactModel(**camelback2snake(contact_info)) contact = contact.flush() contact_link = ContactLinkModel() contact_link.user = user contact_link.contact = contact contact_link.save() return ContactService(contact)
def update_product_subscription(product_subscription_id: int, is_approved: bool, org_id: int, is_new_transaction: bool = True): """Update Product Subscription.""" current_app.logger.debug('<update_task_product ') # Approve/Reject Product subscription product_subscription: ProductSubscriptionModel = ProductSubscriptionModel.find_by_id( product_subscription_id) if is_approved: product_subscription.status_code = ProductSubscriptionStatus.ACTIVE.value else: product_subscription.status_code = ProductSubscriptionStatus.REJECTED.value product_subscription.flush() if is_new_transaction: # Commit the transaction if it's a new transaction db.session.commit() # Get the org and to get admin mail address org: OrgModel = OrgModel.find_by_org_id(org_id) # Find admin email address admin_email = ContactLinkModel.find_by_user_id( org.members[0].user.id).contact.email product_model: ProductCodeModel = ProductCodeModel.find_by_code( product_subscription.product_code) Product.send_approved_product_subscription_notification( admin_email, product_model.description, product_subscription.status_code) if is_approved: ActivityLogPublisher.publish_activity( Activity(org_id, ActivityAction.ADD_PRODUCT_AND_SERVICE.value, name=product_model.description)) current_app.logger.debug('>update_task_product ')
def _notify_admin_about_hold(org, task_model): admin_email = ContactLinkModel.find_by_user_id( org.members[0].user.id).contact.email create_account_signin_route = urllib.parse.quote_plus( f"{current_app.config.get('BCEID_ACCOUNT_SETUP_ROUTE')}/" f'{org.id}') data = { 'remark': task_model.remarks, 'applicationDate': f"{task_model.created.strftime('%m/%d/%Y')}", 'accountId': task_model.relationship_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('resubmitBceidOrg', org_id=org.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
def approve_or_reject(org_id: int, is_approved: bool, token_info: Dict, origin_url: str = None): """Mark the affidavit as approved or rejected.""" current_app.logger.debug('<find_affidavit_by_org_id ') # Get the org and check what's the current status org: OrgModel = OrgModel.find_by_org_id(org_id) # Current User user: UserModel = UserModel.find_by_jwt_token(token=token_info) # If status is PENDING_AFFIDAVIT_REVIEW handle affidavit approve process, else raise error if org.status_code == OrgStatus.PENDING_AFFIDAVIT_REVIEW.value: AffidavitService.approve_or_reject(org_id, is_approved, user) else: raise BusinessException(Error.INVALID_INPUT, None) if is_approved: org.status_code = OrgStatus.ACTIVE.value else: org.status_code = OrgStatus.REJECTED.value org.decision_made_by = user.username org.decision_made_on = datetime.now() # TODO Publish to activity stream org.save() # Find admin email address admin_email = ContactLinkModel.find_by_user_id(org.members[0].user.id).contact.email Org.send_approved_rejected_notification(admin_email, org.name, org.status_code, origin_url) current_app.logger.debug('>find_affidavit_by_org_id ') return Org(org)
def __delete_contact(user): # unlink the user from its contact contact_link = ContactLinkModel.find_by_user_id(user.id) if contact_link: del contact_link.user contact_link.commit() # clean up any orphaned contacts and links if not contact_link.has_links(): contact = contact_link.contact contact_link.delete() contact.delete()
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)) admin_getting_removed: bool = False # Admin can be removed by other admin or staff. #4909 if updated_fields.get('membership_status', None) \ and updated_fields['membership_status'].id == Status.INACTIVE.value \ and self._model.membership_type.code == ADMIN: admin_getting_removed = True if OrgService(self._model.org).get_owner_count() == 1: raise BusinessException(Error.CHANGE_ROLE_FAILED_ONLY_OWNER, 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) is_staff_modifying = 'staff' in token_info.get('realm_access').get('roles') is_bcros_user = self._model.user.login_source == LoginSource.BCROS.value # send mail if staff modifies , not applicable for bcros , only if anything is getting updated if is_staff_modifying and not is_bcros_user and len(updated_fields) != 0: publish_to_mailer(notification_type='teamModified', org_id=self._model.org.id) # send mail to the person itself who is getting removed by staff ;if he is admin if is_staff_modifying and not is_bcros_user and admin_getting_removed: recipient_email = ContactLinkModel.find_by_user_id(self._model.user.id).contact.email data = { 'accountId': self._model.org.id, 'recipientEmail': recipient_email } publish_to_mailer(notification_type='adminRemoved', org_id=self._model.org.id, data=data) current_app.logger.debug('>update_membership') return self
def approve_or_reject(org_id: int, is_approved: bool, origin_url: str = None): """Mark the affidavit as approved or rejected.""" current_app.logger.debug('<find_affidavit_by_org_id ') # Get the org and check what's the current status org: OrgModel = OrgModel.find_by_org_id(org_id) # Current User user: UserModel = UserModel.find_by_jwt_token() # If status is PENDING_STAFF_REVIEW handle affidavit approve process, else raise error if org.status_code == OrgStatus.PENDING_STAFF_REVIEW.value and \ org.access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value): AffidavitService.approve_or_reject(org_id, is_approved, user) elif org.status_code != OrgStatus.PENDING_STAFF_REVIEW.value or \ org.access_type not in \ (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value, AccessType.GOVM.value): raise BusinessException(Error.INVALID_INPUT, None) if is_approved: org.status_code = OrgStatus.ACTIVE.value else: org.status_code = OrgStatus.REJECTED.value org.decision_made_by = user.username org.decision_made_on = datetime.now() # TODO Publish to activity stream org.save() # Find admin email address admin_email = ContactLinkModel.find_by_user_id( org.members[0].user.id).contact.email if org.access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value): Org.send_approved_rejected_notification(admin_email, org.name, org.id, org.status_code, origin_url) elif org.access_type == AccessType.GOVM.value: Org.send_approved_rejected_govm_notification( admin_email, org.name, org.id, org.status_code, origin_url) current_app.logger.debug('>find_affidavit_by_org_id ') return Org(org)
def delete_contact(token): """Delete the contact for an existing user.""" user = UserModel.find_by_jwt_token(token) if not user or not user.contacts: raise BusinessException(Error.DATA_NOT_FOUND, None) # unlink the user from its contact contact_link = ContactLinkModel.find_by_user_id(user.id) del contact_link.user contact_link.commit() # clean up any orphaned contacts and links if not contact_link.has_links(): contact = contact_link.contact contact_link.delete() contact.delete() return User(user)
def update_contact(token, contact_info: dict): """Update a contact for an existing user.""" current_app.logger.debug('update_contact') user = UserModel.find_by_jwt_token(token) if user is None: raise BusinessException(Error.DATA_NOT_FOUND, None) # find the contact link for this user contact_link = ContactLinkModel.find_by_user_id(user.id) # now find the contact for the link 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 = contact.save() # return the updated contact return ContactService(contact)
def update_contact(token, contact_info: dict): """Update a contact for an existing user.""" user = UserModel.find_by_jwt_token(token) if user is None: raise BusinessException(Error.DATA_NOT_FOUND, None) # find the contact link for this user contact_link = ContactLinkModel.find_by_user_id(user.id) # now find the contact for the link 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 = contact.flush() contact.commit() # return the user with the updated contact return User(user)
def add_contact(token, contact_info: dict): """Add or update contact information for an existing user.""" user = UserModel.find_by_jwt_token(token) if user is None: raise BusinessException(Error.DATA_NOT_FOUND, None) # check for existing contact (we only want one contact per user) contact_link = ContactLinkModel.find_by_user_id(user.id) if contact_link is not None: raise BusinessException(Error.DATA_ALREADY_EXISTS, None) contact = ContactModel(**camelback2snake(contact_info)) contact.commit() contact_link = ContactLinkModel() contact_link.user = user contact_link.contact = contact contact_link.commit() return User(user)
def approve_or_reject(org_id: int, is_approved: bool, origin_url: str = None, task_action: str = None): """Mark the affidavit as approved or rejected.""" current_app.logger.debug('<find_affidavit_by_org_id ') # Get the org and check what's the current status org: OrgModel = OrgModel.find_by_org_id(org_id) # Current User user: UserModel = UserModel.find_by_jwt_token() if task_action == TaskAction.AFFIDAVIT_REVIEW.value: AffidavitService.approve_or_reject(org_id, is_approved, user) if is_approved: org.status_code = OrgStatus.ACTIVE.value else: org.status_code = OrgStatus.REJECTED.value org.decision_made_by = user.username org.decision_made_on = datetime.now() # TODO Publish to activity stream org.save() # Find admin email address admin_email = ContactLinkModel.find_by_user_id( org.members[0].user.id).contact.email if org.access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value): Org.send_approved_rejected_notification(admin_email, org.name, org.id, org.status_code, origin_url) elif org.access_type in (AccessType.GOVM.value, AccessType.GOVN.value): Org.send_approved_rejected_govm_govn_notification( admin_email, org.name, org.id, org.status_code, origin_url) current_app.logger.debug('>find_affidavit_by_org_id ') return Org(org)