Example #1
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)
Example #2
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)
Example #3
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()

    return get_managers_dict(signature_acl)
Example #4
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)
    # 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)
Example #5
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()
Example #6
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}
Example #7
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}
Example #8
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()
Example #9
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)
Example #10
0
def update_signature(
        signature_id,  # pylint: disable=too-many-arguments,too-many-return-statements,too-many-branches
        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 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
    """
    signature = Signature()
    try:  # Try to load the signature to update.
        signature.load(str(signature_id))
    except DoesNotExist as err:
        return {'errors': {'signature_id': str(err)}}
    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(
                'update_signature() - 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))
        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(
                'update_signature() - 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)
    if signature_type is not None:
        if signature_type in ['cla', 'dco']:
            signature.set_signature_type(signature_type)
        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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            return {
                'errors': {
                    'github_org_whitelist':
                    'Invalid value passed in for the github org whitelist'
                }
            }

    signature.save()
    return signature.to_dict()
Example #11
0
def update_signature(
        signature_id,  # pylint: disable=too-many-arguments,too-many-return-statements,too-many-branches
        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):
    """
    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 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
    :return: dict representation of the signature object.
    :rtype: dict
    """
    signature = Signature()
    try:  # Try to load the signature to update.
        signature.load(str(signature_id))
    except DoesNotExist as err:
        return {'errors': {'signature_id': str(err)}}
    if signature_project_id is not None:
        try:
            signature.set_signature_project_id(str(signature_project_id))
        except DoesNotExist as err:
            return {'errors': {'signature_project_id': str(err)}}
    # TODO: Ensure signature_reference_id exists.
    if signature_reference_id is not None:
        signature.set_signature_reference_id(signature_reference_id)
    if signature_reference_type is not None:
        signature.set_signature_reference_type(signature_reference_type)
    if signature_type is not None:
        if signature_type in ['cla', 'dco']:
            signature.set_signature_type(signature_type)
        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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            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)
        except KeyError as err:
            return {
                'errors': {
                    'github_whitelist':
                    'Invalid value passed in for the github whitelist'
                }
            }

    signature.save()
    return signature.to_dict()