def test_is_whitelisted_for_email(self) -> None: """ Test a given email to check if whitelisted against ccla_signature """ signature = Signature() signature.get_email_whitelist = Mock(return_value={"*****@*****.**"}) self.assertTrue(utils.is_whitelisted(signature, email="*****@*****.**")) self.assertFalse(utils.is_whitelisted(signature, email="*****@*****.**"))
def test_populate_signature_missing_agreement_date(): tree = ET.fromstring(content_icla_missing_agreement_date) signed_date = "2020-12-21T08:30:10.133" signature = Signature() populate_signature_from_icla_callback(content_icla_agreement_date, tree, signature) assert signature.get_user_docusign_name() == "Example FullName" assert signature.get_user_docusign_date_signed() == signed_date assert signature.get_user_docusign_raw_xml() == content_icla_agreement_date
def test_is_whitelisted_for_domain(self) -> None: """ Test a given email passes domain whitelist check against ccla_signature """ signature = Signature() signature.get_domain_whitelist = Mock(return_value=[".gmail.com"]) self.assertTrue( utils.is_whitelisted(signature, email="*****@*****.**")) self.assertFalse( utils.is_whitelisted(signature, email="*****@*****.**"))
def remove_cla_manager(username, signature_id, lfid): """ Removes the LFID from the project ACL :param username: username of the user :type username: string :param project_id: The ID of the project :type project_id: UUID :param lfid: the lfid (manager username) to be removed to the project acl :type lfid: string """ # Find project signature = Signature() try: signature.load(str(signature_id)) except DoesNotExist as err: return {'errors': {'signature_id': str(err)}} # Validate user is the manager of the project signature_acl = signature.get_signature_acl() if username not in signature_acl: return {'errors': {'user': "******"}} # Avoid to have an empty acl if len(signature_acl) == 1 and username == lfid: return {'errors': {'user': "******"}} # Remove LFID from the acl signature.remove_signature_acl(lfid) signature.save() # Return modified managers return get_managers_dict(signature_acl)
def test_is_whitelisted_for_github_org(self) -> None: """ Test given github user passes github org check against ccla_signature """ self.mock_get.return_value.ok = True github_orgs = [{ 'login': '******', }] self.mock_get.return_value = Mock() self.mock_get.return_value.json.return_value = github_orgs signature = Signature() signature.get_github_org_whitelist = Mock(return_value=['foo-org']) self.assertTrue(utils.is_whitelisted(signature, github_username='******'))
def get_signature(signature_id): """ Returns the CLA signature requested by UUID. :param signature_id: The signature UUID. :type signature_id: UUID :return: dict representation of the signature object. :rtype: dict """ signature = Signature() try: signature.load(signature_id=str(signature_id)) except DoesNotExist as err: return {'errors': {'signature_id': str(err)}} return signature.to_dict()
def handle_bots(bot_list: List[str], signature: Signature) -> None: cla.log.debug(f'Bots: {bot_list}') for bot_name in bot_list: try: user = cla.utils.get_user_instance() users = user.get_user_by_github_username(bot_name) if users is None: cla.log.debug(f'handle_bots - Bot: {bot_name} does not have a user record (None)') bot_user: User = create_bot(bot_name, signature) if bot_user is not None: create_bot_signature(bot_user, signature) else: # Bot does have a user account in the EasyCLA system found = False # Search the list of user records to see if we have a matching company for u in users: if u.get_user_company_id() == signature.get_signature_reference_id(): found = True cla.log.debug('handle_bots - found bot user account - ensuring the signature exists...') create_bot_signature(u, signature) break # We found matching users in our system, but didn't find one with a matching company if not found: cla.log.debug(f'handle_bots - unable to find user {bot_name} ' f'for company: {signature.get_signature_reference_id()} - ' 'creating user record that matches this company...') bot_user: User = create_bot(bot_name, signature) if bot_user is not None: create_bot_signature(bot_user, signature) else: cla.log.warning(f'handle_bots - failed to create user record for: {bot_name}') except DoesNotExist as err: cla.log.debug(f'handle_bots - bot: {bot_name} does not have a user record (DoesNotExist)')
def user_ccla_check(user: User, project_id: str, signature: Signature) -> bool: cla.log.debug(f'CCLA signature found for user: {user} on project: {project_id}, ' f'signature_id: {signature.get_signature_id()}') if signature.get_signature_signed() and signature.get_signature_approved(): cla.log.debug(f'User: {user} has a signed and approved CCLA for project: {project_id}') return True if signature.get_signature_signed(): cla.log.debug(f'User: {user} has CCLA signed with signature_id: {signature.get_signature_id()}, ' f'project: {project_id}, but has not been approved yet') return False else: # Not signed or approved yet. cla.log.debug(f'User: {user} has CCLA with signature_id: {signature.get_signature_id()}, ' f'project: {project_id}, but has not been signed or approved yet') return False
def add_cla_manager(auth_user, signature_id, lfid): """ Adds the LFID to the signature ACL and returns a new list of CLA Managers. :param username: username of the user :type username: string :param signature_id: The ID of the project :type signature_id: UUID :param lfid: the lfid (manager username) to be added to the project acl :type lfid: string """ # Find project signature = Signature() try: signature.load(str(signature_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} # Get Signature ACL signature_acl = signature.get_signature_acl() if auth_user.username not in signature_acl: return { 'errors': { 'user_id': 'You are not authorized to see the managers.' } } company.add_permission(auth_user, lfid, signature.get_signature_reference_id(), ignore_auth_user=True) # Add lfid to acl signature.add_signature_acl(lfid) signature.save() event_data = f'{lfid} added as cla manager to Signature ACL for {signature.get_signature_id()}' Event.create_event( event_data=event_data, event_type=EventType.AddCLAManager, contains_pii=True, ) return get_managers_dict(signature_acl)
def get_signatures(): """ Returns a list of signatures in the CLA system. :return: List of signatures in dict format. :rtype: [dict] """ signatures = [signature.to_dict() for signature in Signature().all()] return signatures
def get_project_signatures(project_id): """ Get all signatures for project. :param project_id: The ID of the project in question. :type project_id: string """ signatures = Signature().get_signatures_by_project(str(project_id), signature_signed=True) return [signature.to_dict() for signature in signatures]
def get_user_signatures(user_id): """ Get all signatures for user. :param user_id: The ID of the user in question. :type user_id: string """ signatures = Signature().get_signatures_by_reference(str(user_id), 'user') return [signature.to_dict() for signature in signatures]
def test_canceled_signature_html(): signature_type = "ccla" signature_return_url = "https://github.com/communitybridge/easycla/pull/227" signature_sign_url = "https://demo.docusign.net/Signing/MTRedeem/v1/4b594c99-d76b-46c4-bf8c-5912b177b0eb?slt=eyJ0eXAiOi" signature = Signature(signature_type=signature_type, signature_return_url=signature_return_url, signature_sign_url=signature_sign_url) result = canceled_signature_html(signature=signature) assert "Ccla" in result assert signature_return_url in result assert signature_sign_url in result signature = Signature(signature_sign_url=signature_sign_url) result = canceled_signature_html(signature=signature) assert "Ccla" not in result assert signature_return_url not in result assert signature_sign_url in result
def get_company_signatures(company_id): """ Get all signatures for company. :param company_id: The ID of the company in question. :type company_id: string """ signatures = Signature().get_signatures_by_reference(company_id, 'company') return [signature.to_dict() for signature in signatures]
def create_bot(bot_name: str, signature: Signature) -> Optional[User]: fn = 'controllers.signature.create_bot' cla.log.debug(f'{fn} - creating Bot: {bot_name}...') user_github_id = lookup_github_user(bot_name) if user_github_id != 0: project: Project = cla.utils.get_project_instance() try: project.load(signature.get_signature_project_id()) except DoesNotExist as err: cla.log.warning( f'{fn} - Unable to load project by id: {signature.get_signature_project_id()}' f' Unable to create bot: {bot_name}') return None the_company: Company = cla.utils.get_company_instance() try: the_company.load(signature.get_signature_reference_id()) except DoesNotExist as err: cla.log.warning( f'{fn} - Unable to load company by id: {signature.get_signature_reference_id()}' f' Unable to create bot: {bot_name}') return None user: User = cla.utils.get_user_instance() user.set_user_id(str(uuid.uuid4())) user.set_user_name(bot_name) user.set_user_github_username(bot_name) user.set_user_github_id(user_github_id) user.set_user_company_id(signature.get_signature_reference_id()) user.set_note( f'{datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")} Added as part of ' f'{project.get_project_name()}, approval list by ' f'{the_company.get_company_name()}') user.save() cla.log.debug(f'{fn} - created bot user: {user}') return user cla.log.warning( f'{fn} - unable to create bot user: {bot_name} - unable to lookup name in GitHub.' ) return None
def get_project_employee_signatures(company_id, project_id): """ Get all employee signatures for project specified and a company specified :param company_id: The ID of the company in question :param project_id: The ID of the project in question :type company_id: string :type project_id: string """ signatures = Signature().get_employee_signatures_by_company_project( str(company_id), str(project_id)) return signatures
def user_icla_check(user: User, project_id: str, signature: Signature, latest_major_version=True) -> bool: cla.log.debug( f'ICLA signature found for user: {user} on project: {project_id}, ' f'signature_id: {signature.get_signature_id()}') # Here's our logic to determine if the signature is valid if latest_major_version: # Ensure it's latest signature. project = get_project_instance() project.load(str(project_id)) document_models = project.get_project_individual_documents() major, _ = get_last_version(document_models) if signature.get_signature_document_major_version() != major: cla.log.debug( f'User: {user} only has an old document version signed ' f'(v{signature.get_signature_document_major_version()}) - needs a new version' ) return False if signature.get_signature_signed() and signature.get_signature_approved(): # Signature found and signed/approved. cla.log.debug( f'User: {user} has ICLA signed and approved signature_id: {signature.get_signature_id()} ' f'for project: {project_id}') return True elif signature.get_signature_signed(): # Not approved yet. cla.log.debug( f'User: {user} has ICLA signed with signature_id: {signature.get_signature_id()}, ' f'project: {project_id}, but has not been approved yet') return False else: # Not signed or approved yet. cla.log.debug( f'User: {user} has ICLA with signature_id: {signature.get_signature_id()}, ' f'project: {project_id}, but has not been signed or approved yet') return False
def get_unsigned_projects_for_company(company_id): """ Returns a list of projects that the company has not signed a CCLA for. :param company_id: The company's ID. :type company_id: string :return: dict representation of the projects object. :rtype: [dict] """ # Verify company is valid company = Company() try: company.load(company_id) except DoesNotExist as err: return {'errors': {'company_id': str(err)}} # get project ids that the company has signed the CCLAs for. signature = Signature() # signed_project_ids = signature.get_projects_by_company_signed(company_id) signed_project_ids = signature.get_projects_by_company_signed(company_id) # from all projects, retrieve projects that are not in the signed project ids # Consider adding attributes_to_get for the projection # unsigned_projects = [project for project in Project().all(attributes_to_get=['project_id']) unsigned_projects = [ project for project in Project().all() if project.get_project_id() not in signed_project_ids ] # filter to get unsigned projects that are not of ccla type ccla_unsigned_projects = [ project.to_dict() for project in unsigned_projects if project.get_project_ccla_enabled() ] return ccla_unsigned_projects
def get_cla_managers(username, signature_id): """ Returns CLA managers from the CCLA signature ID. :param username: The LF username :type username: string :param signature_id: The Signature ID of the CCLA signed. :type signature_id: string :return: dict representation of the project managers. :rtype: dict """ signature = Signature() try: signature.load(str(signature_id)) except DoesNotExist as err: return {'errors': {'signature_id': str(err)}} # Get Signature ACL signature_acl = signature.get_signature_acl() if username not in signature_acl: return {'errors': {'user_id': 'You are not authorized to see the managers.'}} return get_managers_dict(signature_acl)
def create_bot_signature(bot_user: User, signature: Signature) -> Optional[Signature]: cla.log.debug(f'create_bot_signature - locating Bot Signature for: {bot_user.get_user_name()}...') project: Project = cla.utils.get_project_instance() try: project.load(signature.get_signature_project_id()) except DoesNotExist as err: cla.log.warning(f'create_bot_signature - unable to load project by id: {signature.get_signature_project_id()}' f' Unable to create bot: {bot_user}') return None the_company: Company = cla.utils.get_company_instance() try: the_company.load(signature.get_signature_reference_id()) except DoesNotExist as err: cla.log.warning(f'create_bot_signature - unable to load company by id: {signature.get_signature_reference_id()}' f' Unable to create bot: {bot_user}') return None bot_sig: Signature = cla.utils.get_signature_instance() # First, before we create a new one, grab a list of employee signatures for this company/project existing_sigs: List[Signature] = bot_sig.get_employee_signatures_by_company_project_model( company_id=bot_user.get_user_company_id(), project_id=signature.get_signature_project_id()) # Check to see if we have an existing signature for this user/company/project combo for sig in existing_sigs: if sig.get_signature_reference_id() == bot_user.get_user_id(): cla.log.debug('create_bot_signature - found existing bot signature ' f'for user: {bot_user} ' f'with company: {the_company} ' f'for project: {project}') return sig # Didn't find an existing signature, let's create a new one cla.log.debug(f'create_bot_signature - creating Bot Signature: {bot_user.get_user_name()}...') bot_sig.set_signature_id(str(uuid.uuid4())) bot_sig.set_signature_project_id(signature.get_signature_project_id()) bot_sig.set_signature_reference_id(bot_user.get_user_id()) bot_sig.set_signature_document_major_version(signature.get_signature_document_major_version()) bot_sig.set_signature_document_minor_version(signature.get_signature_document_minor_version()) bot_sig.set_signature_approved(True) bot_sig.set_signature_signed(True) bot_sig.set_signature_type('cla') bot_sig.set_signature_reference_type('user') bot_sig.set_signature_user_ccla_company_id(bot_user.get_user_company_id()) bot_sig.set_note(f'{datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")} Added as part of ' f'{project.get_project_name()}, approval list by ' f'{the_company.get_company_name()}') bot_sig.save() cla.log.debug(f'create_bot_signature - created Bot Signature: {bot_sig}') return bot_sig
def test_populate_signature_from_icla_callback(): tree = ET.fromstring(content_icla_agreement_date) agreement_date = "2020-12-21T08:29:20.51" signature = Signature() populate_signature_from_icla_callback(content_icla_agreement_date, tree, signature) assert signature.get_user_docusign_name() == "Example FullName" assert signature.get_user_docusign_date_signed() == agreement_date assert signature.get_user_docusign_raw_xml() == content_icla_agreement_date assert "user_docusign_name" in signature.to_dict(), "" assert "user_docusign_date_signed" in signature.to_dict() assert "user_docusign_raw_xml" not in signature.to_dict() assert "user_docusign_name" in str(signature) assert "user_docusign_date_signed" in str(signature) assert "user_docusign_raw_xml" not in str(signature)
def delete_signature(signature_id): """ Deletes an signature based on UUID. :param signature_id: The UUID of the signature. :type signature_id: UUID """ signature = Signature() try: # Try to load the signature to delete. signature.load(str(signature_id)) except DoesNotExist as err: # Should we bother sending back an error? return {'errors': {'signature_id': str(err)}} signature.delete() return {'success': True}
def get_company_signatures_by_acl(username, company_id): """ Get all signatures for company filtered by it's ACL. A company's signature will be returned only if the provided username appears in the signature's ACL. :param username: The username of the authenticated user :type username: string :param company_id: The ID of the company in question. :type company_id: string """ # Get signatures by company reference all_signatures = Signature().get_signatures_by_reference(company_id, 'company') # Filter signatures this manager is authorized to see signatures = [] for signature in all_signatures: if username in signature.get_signature_acl(): signatures.append(signature) return [signature.to_dict() for signature in signatures]
def test_handle_commit_author_whitelisted(self) -> None: """ Test case where commit authors have no signatures but have been whitelisted and should return missing list containing a whitelisted flag """ # Mock user not existing and happens to be whitelisted self.mock_user_get.return_value.get_user_by_github_id.return_value = None self.mock_user_get.return_value.get_user_by_email.return_value = None self.mock_signature_get.return_value.get_signatures_by_project.return_value = [ Signature() ] self.mock_utils_get.return_value.is_whitelisted.return_value = True missing = [] signed = [] project = Project() project.set_project_id('fake_project_id') handle_commit_from_user(project, 'fake_sha', (123, 'foo', '*****@*****.**'), signed, missing) self.assertListEqual( missing, [('fake_sha', [123, 'foo', '*****@*****.**', True])]) self.assertEqual(signed, [])
def delete_signature(signature_id): """ Deletes an signature based on UUID. :param signature_id: The UUID of the signature. :type signature_id: UUID """ signature = Signature() try: # Try to load the signature to delete. signature.load(str(signature_id)) except DoesNotExist as err: # Should we bother sending back an error? return {'errors': {'signature_id': str(err)}} signature.delete() event_data = f'Deleted signature {signature_id}' Event.create_event( event_data=event_data, event_type=EventType.DeleteSignature, contains_pii=False, ) return {'success': True}
def notify_whitelist_change(auth_user, old_signature: Signature, new_signature: Signature): company_name = new_signature.get_signature_reference_name() project = cla.utils.get_project_instance() project.load(new_signature.get_signature_project_id()) project_name = project.get_project_name() changes = [] domain_msg_added = 'The domain {} was added to the domain approval list.' domain_msg_deleted = 'The domain {} was removed from the domain approval list.' domain_changes, _, _ = change_in_list( old_list=old_signature.get_domain_whitelist(), new_list=new_signature.get_domain_whitelist(), msg_added=domain_msg_added, msg_deleted=domain_msg_deleted) changes = changes + domain_changes email_msg_added = 'The email address {} was added to the email approval list.' email_msg_deleted = 'The email address {} was removed from the email approval list.' email_changes, email_added, email_deleted = change_in_list( old_list=old_signature.get_email_whitelist(), new_list=new_signature.get_email_whitelist(), msg_added=email_msg_added, msg_deleted=email_msg_deleted) changes = changes + email_changes github_msg_added = 'The GitHub user {} was added to the GitHub approval list.' github_msg_deleted = 'The GitHub user {} was removed from the github approval list.' github_changes, github_added, github_deleted = change_in_list( old_list=old_signature.get_github_whitelist(), new_list=new_signature.get_github_whitelist(), msg_added=github_msg_added, msg_deleted=github_msg_deleted) changes = changes + github_changes github_org_msg_added = 'The GitHub organization {} was added to the GitHub organization approval list.' github_org_msg_deleted = 'The GitHub organization {} was removed from the GitHub organization approval list.' github_org_changes, _, _ = change_in_list( old_list=old_signature.get_github_org_whitelist(), new_list=new_signature.get_github_org_whitelist(), msg_added=github_org_msg_added, msg_deleted=github_org_msg_deleted) changes = changes + github_org_changes if len(changes) > 0: # send email to cla managers about change cla_managers = new_signature.get_managers() subject, body, recipients = approval_list_change_email_content( project, company_name, project_name, cla_managers, changes) if len(recipients) > 0: get_email_service().send(subject, body, recipients) cla_manager_name = auth_user.name # send email to contributors notify_whitelist_change_to_contributors( project=project, email_added=email_added, email_removed=email_deleted, github_users_added=github_added, github_users_removed=github_deleted, company_name=company_name, project_name=project_name, cla_manager_name=cla_manager_name) event_data = " ,".join(changes) Event.create_event( event_data=event_data, event_summary=event_data, event_type=EventType.NotifyWLChange, event_company_name=company_name, event_project_name=project_name, contains_pii=True, )
def update_signature( signature_id, # pylint: disable=too-many-arguments,too-many-return-statements,too-many-branches auth_user, signature_project_id=None, signature_reference_id=None, signature_reference_type=None, signature_type=None, signature_approved=None, signature_signed=None, signature_return_url=None, signature_sign_url=None, domain_whitelist=None, email_whitelist=None, github_whitelist=None, github_org_whitelist=None): """ Updates an signature and returns the newly updated signature in dict format. A value of None means the field should not be updated. :param signature_id: ID of the signature. :type signature_id: ID | None :param auth_user: the authenticated user :type auth_user: string :param signature_project_id: Project ID for this signature. :type signature_project_id: string | None :param signature_reference_id: Reference ID for this signature. :type signature_reference_id: string | None :param signature_reference_type: Reference type for this signature. :type signature_reference_type: ['user' | 'company'] | None :param signature_type: New signature type ('cla' or 'dco'). :type signature_type: string | None :param signature_signed: Whether this signature is signed or not. :type signature_signed: boolean | None :param signature_approved: Whether this signature is approved or not. :type signature_approved: boolean | None :param signature_return_url: The URL the user will be sent to after signing. :type signature_return_url: string | None :param signature_sign_url: The URL the user must visit to sign the signature. :type signature_sign_url: string | None :param domain_whitelist: the domain whitelist :param email_whitelist: the email whitelist :param github_whitelist: the github username whitelist :param github_org_whitelist: the github org whitelist :return: dict representation of the signature object. :rtype: dict """ fn = 'controllers.signature.update_signature' cla.log.debug(f'{fn} - loading signature by id: {str(signature_id)}') signature = Signature() try: # Try to load the signature to update. signature.load(str(signature_id)) old_signature = copy.deepcopy(signature) except DoesNotExist as err: return {'errors': {'signature_id': str(err)}} update_str = f'signature {signature_id} updates: \n ' if signature_project_id is not None: # make a note if the project id is set and doesn't match if signature.get_signature_project_id() != str(signature_project_id): cla.log.warning( f'{fn} - project IDs do not match => ' f'record project id: {signature.get_signature_project_id()} != ' f'parameter project id: {str(signature_project_id)}') try: signature.set_signature_project_id(str(signature_project_id)) update_str += f'signature_project_id updated to {signature_project_id} \n' except DoesNotExist as err: return {'errors': {'signature_project_id': str(err)}} # TODO: Ensure signature_reference_id exists. if signature_reference_id is not None: if signature.get_signature_reference_id() != str( signature_reference_id): cla.log.warning( f'{fn} - signature reference IDs do not match => ' f'record signature ref id: {signature.get_signature_reference_id()} != ' f'parameter signature ref id: {str(signature_reference_id)}') signature.set_signature_reference_id(signature_reference_id) if signature_reference_type is not None: signature.set_signature_reference_type(signature_reference_type) update_str += f'signature_reference_type updated to {signature_reference_type} \n' if signature_type is not None: if signature_type in ['cla', 'dco']: signature.set_signature_type(signature_type) update_str += f'signature_type updated to {signature_type} \n' else: return { 'errors': { 'signature_type': 'Invalid value passed. The accepted values are: (cla|dco)' } } if signature_signed is not None: try: val = hug.types.smart_boolean(signature_signed) signature.set_signature_signed(val) update_str += f'signature_signed updated to {signature_signed} \n' except KeyError: return { 'errors': { 'signature_signed': 'Invalid value passed in for true/false field' } } if signature_approved is not None: try: val = hug.types.smart_boolean(signature_approved) update_signature_approved(signature, val) update_str += f'signature_approved updated to {val} \n' except KeyError: return { 'errors': { 'signature_approved': 'Invalid value passed in for true/false field' } } if signature_return_url is not None: try: val = cla.hug_types.url(signature_return_url) signature.set_signature_return_url(val) update_str += f'signature_return_url updated to {val} \n' except KeyError: return { 'errors': { 'signature_return_url': 'Invalid value passed in for URL field' } } if signature_sign_url is not None: try: val = cla.hug_types.url(signature_sign_url) signature.set_signature_sign_url(val) update_str += f'signature_sign_url updated to {val} \n' except KeyError: return { 'errors': { 'signature_sign_url': 'Invalid value passed in for URL field' } } if domain_whitelist is not None: try: domain_whitelist = hug.types.multiple(domain_whitelist) signature.set_domain_whitelist(domain_whitelist) update_str += f'domain_whitelist updated to {domain_whitelist} \n' except KeyError: return { 'errors': { 'domain_whitelist': 'Invalid value passed in for the domain whitelist' } } if email_whitelist is not None: try: email_whitelist = hug.types.multiple(email_whitelist) signature.set_email_whitelist(email_whitelist) update_str += f'email_whitelist updated to {email_whitelist} \n' except KeyError: return { 'errors': { 'email_whitelist': 'Invalid value passed in for the email whitelist' } } if github_whitelist is not None: try: github_whitelist = hug.types.multiple(github_whitelist) signature.set_github_whitelist(github_whitelist) # A little bit of special logic to for GitHub whitelists that have bots bot_list = [ github_user for github_user in github_whitelist if is_github_bot(github_user) ] if bot_list is not None: handle_bots(bot_list, signature) update_str += f'github_whitelist updated to {github_whitelist} \n' except KeyError: return { 'errors': { 'github_whitelist': 'Invalid value passed in for the github whitelist' } } if github_org_whitelist is not None: try: github_org_whitelist = hug.types.multiple(github_org_whitelist) signature.set_github_org_whitelist(github_org_whitelist) update_str += f'github_org_whitelist updated to {github_org_whitelist} \n' except KeyError: return { 'errors': { 'github_org_whitelist': 'Invalid value passed in for the github org whitelist' } } event_data = update_str Event.create_event( event_data=event_data, event_summary=event_data, event_type=EventType.UpdateSignature, contains_pii=True, ) signature.save() notify_whitelist_change(auth_user=auth_user, old_signature=old_signature, new_signature=signature) return signature.to_dict()
def remove_cla_manager(username, signature_id, lfid): """ Removes the LFID from the project ACL :param username: username of the user :type username: string :param project_id: The ID of the project :type project_id: UUID :param lfid: the lfid (manager username) to be removed to the project acl :type lfid: string """ # Find project signature = Signature() try: signature.load(str(signature_id)) except DoesNotExist as err: return {'errors': {'signature_id': str(err)}} # Validate user is the manager of the project signature_acl = signature.get_signature_acl() if username not in signature_acl: return { 'errors': { 'user': "******" } } # Avoid to have an empty acl if len(signature_acl) == 1 and username == lfid: return { 'errors': { 'user': "******" } } # Remove LFID from the acl signature.remove_signature_acl(lfid) signature.save() # get cla managers for email content managers = get_cla_managers(username, signature_id) # Get Company and Project instances try: project = get_project(signature.get_signature_project_id()) except DoesNotExist as err: return err try: company_instance = get_company(signature.get_signature_reference_id()) except DoesNotExist as err: return err # Send email to removed CLA manager # send email to newly added CLA manager try: subject, body, recipients = remove_cla_manager_email_content( lfid, project, company_instance, managers) get_email_service().send(subject, body, recipients) except Exception as err: return { 'errors': {'Failed to send email for lfid: %s , %s ' % (lfid, err)} } event_data = f'User with lfid {lfid} removed from project ACL with signature {signature.get_signature_id()}' Event.create_event( event_data=event_data, event_summary=event_data, event_type=EventType.RemoveCLAManager, contains_pii=True, ) # Return modified managers return get_managers_dict(signature_acl)
def add_cla_manager(auth_user: AuthUser, signature_id: str, lfid: str): """ Adds the LFID to the signature ACL and returns a new list of CLA Managers. :param auth_user: username of the user :type auth_user: string :param signature_id: The ID of the project :type signature_id: UUID :param lfid: the lfid (manager username) to be added to the project acl :type lfid: string """ # Find project signature = Signature() try: signature.load(signature_id) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} # Get Signature ACL signature_acl = signature.get_signature_acl() if auth_user.username not in signature_acl: return { 'errors': { 'user_id': 'You are not authorized to see the managers.' } } company.add_permission(auth_user, lfid, signature.get_signature_reference_id(), ignore_auth_user=True) # Get Company and Project instances try: project = get_project(signature.get_signature_project_id()) except DoesNotExist as err: return err try: company_instance = get_company(signature.get_signature_reference_id()) except DoesNotExist as err: return err # get cla managers for email content managers = get_cla_managers(auth_user.username, signature_id) # Add lfid to acl signature.add_signature_acl(lfid) signature.save() # send email to newly added CLA manager try: subject, body, recipients = add_cla_manager_email_content( lfid, project, company_instance, managers) get_email_service().send(subject, body, recipients) except Exception as err: return { 'errors': {'Failed to send email for lfid: %s , %s ' % (lfid, err)} } event_data = f'{lfid} added as cla manager to Signature ACL for {signature.get_signature_id()}' Event.create_event( event_data=event_data, event_summary=event_data, event_type=EventType.AddCLAManager, contains_pii=True, ) return get_managers_dict(signature_acl)
def signature_instance(): """ Mock signature instance """ with patch(PATCH_METHOD) as req: req.return_value = SIGNATURE_TABLE_DATA instance = Signature() instance.set_signature_id("sig_id") instance.set_signature_project_id("proj_id") instance.set_signature_reference_id("ref_id") instance.set_signature_type("type") instance.set_signature_project_external_id("proj_id") instance.set_signature_company_signatory_id("comp_sig_id") instance.set_signature_company_signatory_name("name") instance.set_signature_company_signatory_email("email") instance.set_signature_company_initial_manager_id("manager_id") instance.set_signature_company_initial_manager_name("manager_name") instance.set_signature_company_initial_manager_email("manager_email") instance.set_signature_company_secondary_manager_list({"foo": "bar"}) instance.set_signature_document_major_version(1) instance.set_signature_document_minor_version(2) instance.save() yield instance