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 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 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)
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)
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 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 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 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 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()
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()