Esempio n. 1
0
 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="*****@*****.**"))
Esempio n. 2
0
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
Esempio n. 3
0
 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="*****@*****.**"))
Esempio n. 4
0
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)
Esempio n. 5
0
 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='******'))
Esempio n. 6
0
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()
Esempio n. 7
0
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)')
Esempio n. 8
0
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
Esempio n. 9
0
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)
Esempio n. 10
0
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
Esempio n. 11
0
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]
Esempio n. 12
0
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]
Esempio n. 13
0
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
Esempio n. 14
0
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]
Esempio n. 15
0
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
Esempio n. 16
0
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
Esempio n. 17
0
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
Esempio n. 18
0
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
Esempio n. 19
0
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)
Esempio n. 20
0
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
Esempio n. 21
0
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)
Esempio n. 22
0
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}
Esempio n. 23
0
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]
Esempio n. 24
0
 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, [])
Esempio n. 25
0
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}
Esempio n. 26
0
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,
    )
Esempio n. 27
0
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()
Esempio n. 28
0
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)
Esempio n. 29
0
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)
Esempio n. 30
0
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