def notify_project_managers(repositories): if repositories is None: return project_repos = {} for ghrepo in repositories: project_id = ghrepo.get_repository_project_id() if project_id in project_repos: project_repos[project_id].append(ghrepo.get_repository_url()) else: project_repos[project_id] = [ghrepo.get_repository_url()] for project_id in project_repos: managers = cla.controllers.project.get_project_managers("", project_id, enable_auth=False) project = get_project_instance() try: project.load(project_id=str(project_id)) except DoesNotExist as err: cla.log.warning('notify_project_managers - unable to load project (cla_group) by ' f'project_id: {project_id}, error: {err}') return {'errors': {'project_id': str(err)}} repositories = project_repos[project_id] subject, body, recipients = unable_to_do_cla_check_email_content( project, managers, repositories) get_email_service().send(subject, body, recipients) cla.log.debug('github.activity - sending unable to perform CLA Check email' f' to managers: {recipients}' f' for project {project} with ' f' repositories: {repositories}')
def delete_project_document(project_id, document_type, major_version, minor_version, username=None): """ Deletes the document from the specified project. :param project_id: The ID of the project in question. :type project_id: string :param document_type: The type of document to remove (individual or corporate). :type document_type: string :param major_version: The document major version number to remove. :type major_version: integer :param minor_version: The document minor version number to remove. :type minor_version: integer """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) document = cla.utils.get_project_document(project, document_type, major_version, minor_version) if document is None: return {'errors': {'document': 'Document version not found'}} if document_type == 'individual': project.remove_project_individual_document(document) else: project.remove_project_corporate_document(document) project.save() return {'success': True}
def create_project(project_external_id, project_name, project_icla_enabled, project_ccla_enabled, project_ccla_requires_icla_signature, project_acl_username): """ Creates a project and returns the newly created project in dict format. :param project_external_id: The project's external ID. :type project_external_id: string :param project_name: The project's name. :type project_name: string :param project_icla_enabled: Whether or not the project supports ICLAs. :type project_icla_enabled: bool :param project_ccla_enabled: Whether or not the project supports CCLAs. :type project_ccla_enabled: bool :param project_ccla_requires_icla_signature: Whether or not the project requires ICLA with CCLA. :type project_ccla_requires_icla_signature: bool :return: dict representation of the project object. :rtype: dict """ project = get_project_instance() project.set_project_id(str(uuid.uuid4())) project.set_project_external_id(str(project_external_id)) project.set_project_name(project_name) project.set_project_icla_enabled(project_icla_enabled) project.set_project_ccla_enabled(project_ccla_enabled) project.set_project_ccla_requires_icla_signature( project_ccla_requires_icla_signature) project.set_project_acl(project_acl_username) project.save() return project.to_dict()
def notify_project_managers_auto_enabled(organization_name, repositories): if repositories is None: return project_repos = {} for repo in repositories: project_id = repo.get_repository_project_id() if project_id in project_repos: project_repos[project_id].append(repo.get_repository_url()) else: project_repos[project_id] = [repo.get_repository_url()] for project_id in project_repos: managers = cla.controllers.project.get_project_managers("", project_id, enable_auth=False) project = get_project_instance() try: project.load(project_id=str(project_id)) except DoesNotExist as err: cla.log.warning('notify_project_managers_auto_enabled - unable to load project (cla_group) by ' f'project_id: {project_id}, error: {err}') return {'errors': {'project_id': str(err)}} repositories = project_repos[project_id] subject, body, recipients = auto_enabled_repository_email_content( project, managers, organization_name, repositories) get_email_service().send(subject, body, recipients) cla.log.debug('notify_project_managers_auto_enabled - sending auto-enable email ' f' to managers: {recipients}' f' for project {project} for ' f' GitHub Organization {organization_name} with ' f' repositories: {repositories}')
def get_project_companies(project_id): """ Get a project's associated companies (via CCLA link). :param project_id: The ID of the project. :type project_id: string """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} # Get all reference_ids of signatures that match project_id AND are of reference type 'company'. # Return all the companies matching those reference_ids. signature = Signature() signatures = signature.get_signatures_by_project(str(project_id), signature_signed=True, signature_approved=True, signature_reference_type='company') company_ids = list(set([signature.get_signature_reference_id() for signature in signatures])) company = Company() all_companies = [comp.to_dict() for comp in company.all(company_ids)] all_companies = sorted(all_companies, key=lambda i: i['company_name'].casefold()) return all_companies
def delete_project(project_id, username=None): """ Deletes an project based on ID. :TODO: Need to also delete the documents saved with the storage provider. :param project_id: The ID of the project. :type project_id: string """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) # Create audit trail event_data = 'Project-{} deleted'.format(project.get_project_name()) Event.create_event( event_type=EventType.DeleteProject, event_project_id=project_id, event_data=event_data, contains_pii=False, ) project.delete() return {'success': True}
def _get_project_document(project_id, document_type, major_version=None, minor_version=None): """ See documentation for get_project_document(). """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} if document_type == 'individual': try: document = project.get_project_individual_document( major_version, minor_version) except DoesNotExist as err: return {'errors': {'document': str(err)}} else: try: document = project.get_project_corporate_document( major_version, minor_version) except DoesNotExist as err: return {'errors': {'document': str(err)}} return document
def get_projects(): """ Returns a list of projects in the CLA system. :return: List of projects in dict format. :rtype: [dict] """ return [project.to_dict() for project in get_project_instance().all()]
def handle_installation_repositories_removed_event(action: str, body: dict): func_name = 'github.activity.handle_installation_repositories_removed_event' # Who triggered the event user_login = body['sender']['login'] cla.log.debug( f'{func_name} - processing github [installation_repositories] ' f'activity {action} callback created by GitHub user {user_login}.') repository_removed = body['repositories_removed'] repositories = [] for repo in repository_removed: repository_external_id = repo['id'] ghrepo = Repository().get_repository_by_external_id( repository_external_id, 'github') if ghrepo is not None: repositories.append(ghrepo) # Notify the Project Managers that the following list of repositories were removed notify_project_managers(repositories) # The following list of repositories were deleted/removed from GitHub - we need to remove # the repo entry from our repos table for repo in repositories: project_model = get_project_instance() try: project_model.load(project_id=repo.get_repository_project_id()) except DoesNotExist as err: cla.log.warning( f'{func_name} - unable to load project (cla_group) by ' f'project_id: {repo.get_repository_project_id()}, error: {err}' ) msg = ( f'Disabling repository {repo.get_repository_name()} ' f'from GitHub organization : {repo.get_repository_organization_name()} ' f'with URL: {repo.get_repository_url()} ' 'from the CLA configuration.') cla.log.debug(msg) # Disable the repo and add a note repo.set_enabled(False) repo.add_note(f'{datetime.now()} - Disabling repository due to ' 'GitHub installation_repositories delete event ' f'for CLA Group {project_model.get_project_name()}') repo.save() # Log the event Event.create_event( event_type=EventType.RepositoryDisable, event_project_id=repo.get_repository_project_id(), event_project_name=project_model.get_project_name(), event_company_id=None, event_data=msg, event_summary=msg, event_user_id=user_login, contains_pii=False, )
def update_project(project_id, project_name=None, project_icla_enabled=None, project_ccla_enabled=None, project_ccla_requires_icla_signature=None, username=None): """ Updates a project and returns the newly updated project in dict format. A value of None means the field should not be updated. :param project_id: ID of the project to update. :type project_id: string :param project_name: New project name. :type project_name: string | None :param project_icla_enabled: Whether or not the project supports ICLAs. :type project_icla_enabled: bool | None :param project_ccla_enabled: Whether or not the project supports CCLAs. :type project_ccla_enabled: bool | None :param project_ccla_requires_icla_signature: Whether or not the project requires ICLA with CCLA. :type project_ccla_requires_icla_signature: bool | None :return: dict representation of the project object. :rtype: dict """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) updated_string = " " if project_name is not None: project.set_project_name(project_name) updated_string += f"project_name changed to {project_name} \n" if project_icla_enabled is not None: project.set_project_icla_enabled(project_icla_enabled) updated_string += f"project_icla_enabled changed to {project_icla_enabled} \n" if project_ccla_enabled is not None: project.set_project_ccla_enabled(project_ccla_enabled) updated_string += f"project_ccla_enabled changed to {project_ccla_enabled} \n" if project_ccla_requires_icla_signature is not None: project.set_project_ccla_requires_icla_signature( project_ccla_requires_icla_signature) updated_string += f"project_ccla_requires_icla_signature changed to {project_ccla_requires_icla_signature} \n" project.save() # Create audit trail event_data = f'Project- {project_id} Updates: ' + updated_string Event.create_event( event_type=EventType.UpdateProject, event_project_id=project.get_project_id(), event_data=event_data, event_summary=event_data, contains_pii=False, ) return project.to_dict()
def get_project(project_id, user_id=None): """ Returns the CLA project requested by ID. :param project_id: The project's ID. :type project_id: string :return: dict representation of the project object. :rtype: dict """ project = get_project_instance() try: project.load(project_id=str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} return project.to_dict()
def get_agreement_html(gerrit_id, contract_type): console_v1_endpoint = cla.conf['CONTRIBUTOR_BASE_URL'] console_v2_endpoint = cla.conf['CONTRIBUTOR_V2_BASE_URL'] console_url = '' try: gerrit = get_gerrit_instance() cla.log.debug(f'get_agreement_html - {contract_type} - ' f'Loading gerrit record by gerrit id: {str(gerrit_id)}') gerrit.load(str(gerrit_id)) cla.log.debug( f'get_agreement_html - {contract_type} - Loaded gerrit record: {str(gerrit)}' ) except DoesNotExist as err: return {'errors': {'gerrit_id': str(err)}} try: project = get_project_instance() cla.log.debug( f'get_agreement_html - {contract_type} - ' f'Loading project record by cla group id: {str(gerrit.get_project_id())}' ) project.load(str(gerrit.get_project_id())) cla.log.debug( f'get_agreement_html - {contract_type} - Loaded project record: {str(project)}' ) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} # Temporary condition until all CLA Groups are ready for the v2 Contributor Console if project.get_version() == 'v2': # Generate url for the v2 console # Note: we pass the CLA Group (project_id) in the v2 API call, not the gerrit_id value console_url = (f'https://{console_v2_endpoint}/' f'#/cla/gerrit/project/{gerrit.get_project_id()}/' f'{contract_type}?redirect={gerrit.get_gerrit_url()}') else: # Generate url for the v1 contributor console # Note: we pass the Gerrit ID in the v1 API call, not the CLA Group (project_id) value console_url = (f'https://{console_v1_endpoint}/' f'#/cla/gerrit/project/{gerrit.get_project_id()}/' f'{contract_type}?redirect={gerrit.get_gerrit_url()}') cla.log.debug(f'redirecting user to: {console_url}') contract_type_title = contract_type.title() return f"""
def delete_project(project_id, username=None): """ Deletes an project based on ID. :TODO: Need to also delete the documents saved with the storage provider. :param project_id: The ID of the project. :type project_id: string """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) project.delete() return {'success': True}
def delete_project_document(project_id, document_type, major_version, minor_version, username=None): """ Deletes the document from the specified project. :param project_id: The ID of the project in question. :type project_id: string :param document_type: The type of document to remove (individual or corporate). :type document_type: string :param major_version: The document major version number to remove. :type major_version: integer :param minor_version: The document minor version number to remove. :type minor_version: integer """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) document = cla.utils.get_project_document(project, document_type, major_version, minor_version) if document is None: return {'errors': {'document': 'Document version not found'}} if document_type == 'individual': project.remove_project_individual_document(document) else: project.remove_project_corporate_document(document) project.save() event_data = ( f'Project {project.get_project_name()} with {document_type} :' + f'document type , minor version : {minor_version}, major version : {major_version} deleted' ) Event.create_event( event_data=event_data, event_summary=event_data, event_project_id=project_id, event_type=EventType.DeleteProjectDocument, contains_pii=False, ) return {'success': True}
def create_project(project_external_id, project_name, project_icla_enabled, project_ccla_enabled, project_ccla_requires_icla_signature, project_acl_username): """ Creates a project and returns the newly created project in dict format. :param project_external_id: The project's external ID. :type project_external_id: string :param project_name: The project's name. :type project_name: string :param project_icla_enabled: Whether or not the project supports ICLAs. :type project_icla_enabled: bool :param project_ccla_enabled: Whether or not the project supports CCLAs. :type project_ccla_enabled: bool :param project_ccla_requires_icla_signature: Whether or not the project requires ICLA with CCLA. :type project_ccla_requires_icla_signature: bool :return: dict representation of the project object. :rtype: dict """ project = get_project_instance() project.set_project_id(str(uuid.uuid4())) project.set_project_external_id(str(project_external_id)) project.set_project_name(project_name) project.set_project_icla_enabled(project_icla_enabled) project.set_project_ccla_enabled(project_ccla_enabled) project.set_project_ccla_requires_icla_signature( project_ccla_requires_icla_signature) project.set_project_acl(project_acl_username) project.save() # Create audit trail event_data = 'Project-{} created'.format(project_name) Event.create_event( event_type=EventType.CreateProject, event_project_id=project.get_project_id(), event_data=event_data, event_summary=event_data, contains_pii=False, ) return project.to_dict()
def update_project(project_id, project_name=None, project_icla_enabled=None, project_ccla_enabled=None, project_ccla_requires_icla_signature=None, username=None): """ Updates a project and returns the newly updated project in dict format. A value of None means the field should not be updated. :param project_id: ID of the project to update. :type project_id: string :param project_name: New project name. :type project_name: string | None :param project_icla_enabled: Whether or not the project supports ICLAs. :type project_icla_enabled: bool | None :param project_ccla_enabled: Whether or not the project supports CCLAs. :type project_ccla_enabled: bool | None :param project_ccla_requires_icla_signature: Whether or not the project requires ICLA with CCLA. :type project_ccla_requires_icla_signature: bool | None :return: dict representation of the project object. :rtype: dict """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) if project_name is not None: project.set_project_name(project_name) if project_icla_enabled is not None: project.set_project_icla_enabled(project_icla_enabled) if project_ccla_enabled is not None: project.set_project_ccla_enabled(project_ccla_enabled) if project_ccla_requires_icla_signature is not None: project.set_project_ccla_requires_icla_signature( project_ccla_requires_icla_signature) project.save() return project.to_dict()
def test_create_event(): """ Test endpoint that creates event instance """ url = "/v1/events" event_project_id = str(uuid.uuid4()) event_company_id = str(uuid.uuid4()) user_id = str(uuid.uuid4()) payload = { "event_type": "cla", "event_company_id": event_company_id, "event_project_id": event_project_id, "user_id": user_id, "event_data": json.dumps({"foo": "bar"}), } response = hug.test.post(routes, url, payload) assert response.status == HTTP_400 user = get_user_instance() user.set_user_id(user_id) user.save() company = get_company_instance() company.set_company_id(event_company_id) company.set_company_name("foobar") company.save() project = get_project_instance() project.set_project_name("project") project.set_project_external_id(str(uuid.uuid4())) project.set_project_id(event_project_id) project.save() response = hug.test.post(routes, url, payload) assert response.status == HTTP_200 assert response.data["data"]["event_type"] == "cla" assert response.data["data"]["event_company_id"] == event_company_id assert response.data["data"]["event_project_id"] == event_project_id assert response.data["data"]["user_id"] == user_id assert response.data["data"]["event_data"] == json.dumps({"foo": "bar"})
# Copyright The Linux Foundation and each contributor to CommunityBridge. # SPDX-License-Identifier: MIT # Project external ID. PROJECT_EXTERNAL_ID = 'a090t0000008DEiAAM' # The GitHub user/org used for testing purposes. GITHUB_ORGANIZATION_NAME = 'linuxfoundation' GITHUB_INSTALLATION_ID = 74230 # NOT THE APP ID - find it in the webhook request JSON or URL when viewing installed apps. import sys sys.path.append('../') import cla from cla.utils import get_project_instance, get_github_organization_instance # Organisation project = get_project_instance().get_projects_by_external_id( PROJECT_EXTERNAL_ID)[0] cla.log.info('Creating GitHub Organization: %s' % GITHUB_ORGANIZATION_NAME) github_org = get_github_organization_instance() github_org.set_organization_name(GITHUB_ORGANIZATION_NAME) github_org.set_organization_project_id(project.get_project_id()) # This will be different everytime the CLA app is installed. github_org.set_organization_installation_id(GITHUB_INSTALLATION_ID) github_org.save()
def post_project_document_template(project_id, document_type, document_name, document_preamble, document_legal_entity_name, template_name, new_major_version=None, username=None): """ Will create a new document for the project specified, using the existing template. :param project_id: The ID of the project to add this document to. :type project_id: string :param document_type: The type of document (individual or corporate). :type document_type: string :param document_name: The name of this new document. :type document_name: string :param document_preamble: The document preamble. :type document_preamble: string :param document_legal_entity_name: The legal entity name on the document. :type document_legal_entity_name: string :param template_name: The name of the template object to use. :type template_name: string :param new_major_version: Whether or not to bump up the major version. :type new_major_version: boolean """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) document = get_document_instance() document.set_document_name(document_name) document.set_document_preamble(document_preamble) document.set_document_legal_entity_name(document_legal_entity_name) if document_type == 'individual': major, minor = cla.utils.get_last_version(project.get_project_individual_documents()) if new_major_version: document.set_document_major_version(major + 1) document.set_document_minor_version(0) else: document.set_document_minor_version(minor + 1) project.add_project_individual_document(document) else: major, minor = cla.utils.get_last_version(project.get_project_corporate_documents()) if new_major_version: document.set_document_major_version(major + 1) document.set_document_minor_version(0) else: document.set_document_minor_version(minor + 1) project.add_project_corporate_document(document) # Need to take the template, inject the preamble and legal entity name, and add the tabs. tmplt = getattr(cla.resources.contract_templates, template_name) template = tmplt(document_type=document_type.capitalize(), major_version=document.get_document_major_version(), minor_version=document.get_document_minor_version()) content = template.get_html_contract(document_legal_entity_name, document_preamble) pdf_generator = get_pdf_service() pdf_content = pdf_generator.generate(content) document.set_document_content_type('storage+pdf') document.set_document_content(pdf_content, b64_encoded=False) document.set_raw_document_tabs(template.get_tabs()) project.save() # Create audit trail event_data = 'Project Document created for project {} created with template {}'.format( project.get_project_name(), template_name) Event.create_event( event_type=EventType.CreateProjectDocumentTemplate, event_project_id=project.get_project_id(), event_data=event_data, contains_pii=False, ) return project.to_dict()
# Copyright The Linux Foundation and each contributor to CommunityBridge. # SPDX-License-Identifier: MIT # Project external ID. PROJECT_EXTERNAL_ID1 = 'a090t0000008DEiAAM' PROJECT_EXTERNAL_ID2 = 'a090t0000008E7iAAE' import sys sys.path.append('../') import uuid import cla from cla.utils import get_project_instance ## Project cla.log.info('Creating first project for %s', PROJECT_EXTERNAL_ID1) github_project = get_project_instance() github_project.set_project_id(str(uuid.uuid4())) github_project.set_project_external_id(PROJECT_EXTERNAL_ID1) github_project.set_project_name('Test Project One') github_project.set_project_ccla_requires_icla_signature(False) github_project.save() cla.log.info('Creating second project for %s', PROJECT_EXTERNAL_ID2) github_project = get_project_instance() github_project.set_project_id(str(uuid.uuid4())) github_project.set_project_external_id(PROJECT_EXTERNAL_ID2) github_project.set_project_name('Test Project Two') github_project.set_project_ccla_requires_icla_signature(True) github_project.save()
def post_project_document(project_id, document_type, document_name, document_content_type, document_content, document_preamble, document_legal_entity_name, new_major_version=None, username=None): """ Will create a new document for the project specified. :param project_id: The ID of the project to add this document to. :type project_id: string :param document_type: The type of document (individual or corporate). :type document_type: string :param document_name: The name of this new document. :type document_name: string :param document_content_type: The content type of this document ('pdf', 'url+pdf', 'storage+pdf', etc). :type document_content_type: string :param document_content: The content of the document (or URL to content if content type starts with 'url+'. :type document_content: string or binary data :param document_preamble: The document preamble. :type document_preamble: string :param document_legal_entity_name: The legal entity name on the document. :type document_legal_entity_name: string :param new_major_version: Whether or not to bump up the major version. :type new_major_version: boolean """ project = get_project_instance() try: project.load(str(project_id)) except DoesNotExist as err: return {'errors': {'project_id': str(err)}} project_acl_verify(username, project) document = get_document_instance() document.set_document_name(document_name) document.set_document_content_type(document_content_type) document.set_document_content(document_content) document.set_document_preamble(document_preamble) document.set_document_legal_entity_name(document_legal_entity_name) if document_type == 'individual': major, minor = cla.utils.get_last_version(project.get_project_individual_documents()) if new_major_version: document.set_document_major_version(major + 1) document.set_document_minor_version(0) else: if major == 0: major = 1 document.set_document_major_version(major) document.set_document_minor_version(minor + 1) project.add_project_individual_document(document) else: major, minor = cla.utils.get_last_version(project.get_project_corporate_documents()) if new_major_version: document.set_document_major_version(major + 1) document.set_document_minor_version(0) else: if major == 0: major = 1 document.set_document_major_version(major) document.set_document_minor_version(minor + 1) project.add_project_corporate_document(document) project.save() # Create audit trail event_data = 'Created new document for Project-{} '.format(project.get_project_name()) Event.create_event( event_type=EventType.CreateProjectDocument, event_project_id=project.get_project_id(), event_data=event_data, contains_pii=False, ) return project.to_dict()
def return_url(signature_id, event=None): # pylint: disable=unused-argument """ Handle the GET request from the user once they have successfully signed. :param signature_id: The ID of the signature they have just signed. :type signature_id: string :param event: The event GET flag sent back from the signing service provider. :type event: string | None """ fn = 'return_url' try: # Load the signature based on ID. signature = get_signature_instance() signature.load(str(signature_id)) except DoesNotExist as err: cla.log.error('%s - Invalid signature_id provided when trying to send user back to their ' + \ 'return_url after signing: %s', fn, signature_id) return {'errors': {'signature_id': str(err)}} # Ensure everything went well on the signing service provider's side. if event is not None: # Expired signing URL - the user was redirected back immediately but still needs to sign. if event == 'ttl_expired' and not signature.get_signature_signed(): # Need to re-generate a sign_url and try again. cla.log.info( 'DocuSign URL used was expired, re-generating sign_url') callback_url = signature.get_signature_callback_url() get_signing_service().populate_sign_url(signature, callback_url) signature.save() raise falcon.HTTPFound(signature.get_signature_sign_url()) if event == 'cancel': return canceled_signature_html(signature=signature) ret_url = signature.get_signature_return_url() if ret_url is not None: cla.log.info('%s- Signature success - sending user to return_url: %s', fn, ret_url) try: project = get_project_instance() project.load(str(signature.get_signature_project_id())) except DoesNotExist as err: cla.log.error('%s - Invalid project_id provided when trying to send user back to'\ 'their return_url : %s', fn, signature.get_signature_project_id()) if project.get_version() == 'v2': if signature.get_signature_reference_type() == 'company': cla.log.info('%s - Getting company instance : %s ', fn, signature.get_signature_reference_id()) try: company = get_company_instance() company.load(str(signature.get_signature_reference_id())) except DoesNotExist as err: cla.log.error('%s - Invalid company_id provided : err: %s', fn, signature.get_signature_reference_id) user_service = UserService cla.log.info( '%s - Checking if cla managers have cla-manager role permission', fn) num_tries = 10 i = 1 cla.log.info( f'{fn} - checking if managers:{signature.get_signature_acl()} have roles with {num_tries} tries' ) while i <= num_tries: cla.log.info(f'{fn} - check try #: {i}') assigned = {} for manager in signature.get_signature_acl(): cla.log.info( f'{fn}- Checking {manager} for {CLA_MANAGER_ROLE} for company: {company.get_company_external_id()}, cla_group_id: {signature.get_signature_project_id()}' ) assigned[manager] = user_service.has_role( manager, CLA_MANAGER_ROLE, company.get_company_external_id(), signature.get_signature_project_id()) cla.log.info(f'{fn} - Assigned status : {assigned}') #Ensure that assigned list doesnt have any False values -> All Managers have role assigned if all(list(assigned.values())): cla.log.info( f'All managers have cla-manager role for company: {company.get_company_external_id()} and cla_group_id: {signature.get_signature_project_id()}' ) break time.sleep(0.5) i += 1 raise falcon.HTTPFound(ret_url) cla.log.info('No return_url set for signature - returning success message') return {'success': 'Thank you for signing'}
import sys sys.path.append('../') import uuid import cla from cla.utils import get_project_instance, get_user_instance, get_document_instance, get_github_organization_instance, get_project_instance, get_pdf_service, get_company_instance, get_signature_instance from cla.resources.contract_templates import CNCFTemplate # Project external ID. PROJECT_EXTERNAL_ID = 'a0941000002wByZAAU' ## Project cla.log.info('Creating first project for %s', PROJECT_EXTERNAL_ID) project = get_project_instance() project.set_project_id(str(uuid.uuid4())) project.set_project_external_id(PROJECT_EXTERNAL_ID) project.set_project_name('Test Project One') project.set_project_ccla_requires_icla_signature(False) project.save() ## Create CCLA Document corporate_template = CNCFTemplate(document_type='Corporate', major_version=1, minor_version=0) content = corporate_template.get_html_contract("", "") pdf_generator = get_pdf_service() pdf_content = pdf_generator.generate(content) ## CCLA
def handle_installation_repositories_added_event(action: str, body: dict): func_name = 'github.activity.handle_installation_repositories_added_event' # Who triggered the event user_login = body['sender']['login'] cla.log.debug(f'{func_name} - processing github [installation_repositories] ' f'activity {action} callback created by GitHub user {user_login}.') # Grab the list of repositories added from the event model repository_added = body.get('repositories_added', []) # Create a unique list of repositories for the email that we need to send out repository_list = set([repo.get('full_name', None) for repo in repository_added]) # All the repos in the message should be under the same GitHub Organization organization_name = '' for repo in repository_added: # Grab the information repository_external_id = repo['id'] # example: 271841254 repository_name = repo['name'] # example: PyImath repository_full_name = repo['full_name'] # example: AcademySoftwareFoundation/PyImath organization_name = repository_full_name.split('/')[0] # example: AcademySoftwareFoundation # repository_private = repo['private'] # example: False # Lookup the GitHub Organization in our table - should be there already cla.log.debug(f'{func_name} - Locating organization using name: {organization_name}') org_model = get_organization_model(organization_name) if org_model is None: # Should we create since it's missing? cla.log.warning(f'Unable to locate GitHub Organization {organization_name} in our database') continue # Should we update to ensure the installation_id is set? if org_model.get_organization_installation_id() is None: # Update the installation ID org_model.set_organization_installation_id(body.get('installation', {}).get('id', None)) org_model.save() # Check to see if the auto enabled flag is set if org_model.get_auto_enabled(): # We need to check that we only have 1 CLA Group - auto-enable only works when the entire # Organization falls under a single CLA Group - otherwise, how would we know which CLA Group # to add them to? First we query all the existing repositories associated with this Github Org - # they should all point the the single CLA Group - let's verify this... existing_github_repositories = Repository().get_repositories_by_organization(organization_name) cla_group_ids = set(()) # hoping for only 1 unique value - set collection discards duplicates cla_group_repo_sfids = set(()) # keep track of the existing SFDC IDs from existing repos for existing_repo in existing_github_repositories: cla_group_ids.add(existing_repo.get_repository_project_id()) cla_group_repo_sfids.add(existing_repo.get_repository_sfdc_id()) # We should only have one... if len(cla_group_ids) != 1 or len(cla_group_repo_sfids) != 1: cla.log.warning(f'{func_name} - Auto Enabled set for Organization {organization_name}, ' f'but we found repositories or SFIDs that belong to multiple CLA Groups. ' 'Auto Enable only works when all repositories under a given ' 'GitHub Organization are associated with a single CLA Group. This ' f'organization is associated with {len(cla_group_ids)} CLA Groups and ' f'{len(cla_group_repo_sfids)} SFIDs.') return cla_group_id = cla_group_ids.pop() project_model = get_project_instance() try: project_model.load(project_id=cla_group_id) except DoesNotExist as err: cla.log.warning(f'{func_name} - unable to load project (cla_group) by ' f'project_id: {cla_group_id}, error: {err}') cla.log.debug(f'{func_name} - Organization {organization_name} has auto_enabled set - ' f'adding repository: {repository_name} to ' f'CLA Group: {project_model.get_project_name()}') try: # Create the new repository entry and associate it with the CLA Group new_repository = Repository( repository_id=str(uuid.uuid4()), repository_project_id=cla_group_id, repository_name=repository_full_name, repository_type='github', repository_url='https://github.com/' + repository_full_name, repository_organization_name=organization_name, repository_external_id=repository_external_id, repository_sfdc_id=cla_group_repo_sfids.pop(), ) new_repository.set_enabled(True) new_repository.save() # Log the event msg = (f'Adding repository {repository_full_name} ' f'from GitHub organization : {organization_name} ' f'with URL: https://github.com/{repository_full_name} ' 'to the CLA configuration. GitHub organization was set to auto-enable.') Event.create_event( event_type=EventType.RepositoryAdded, event_project_id=cla_group_id, event_project_name=project_model.get_project_name(), event_company_id=None, event_data=msg, event_summary=msg, event_user_id=user_login, contains_pii=False, ) except Exception as err: cla.log.warning(f'{func_name} - Could not create GitHub repository: {err}') return else: cla.log.debug(f'{func_name} - Auto enabled NOT set for GitHub Organization {organization_name} - ' f'not auto-adding repository: {repository_full_name}') return # Notify the Project Managers notify_project_managers_auto_enabled(organization_name, repository_list)
""" import uuid import sys sys.path.append('../') import cla from cla.utils import get_signature_instance, get_user_instance, get_project_instance, \ get_company_instance PROJECT_EXTERNAL_ID1 = 'a090t0000008DEiAAM' PROJECT_EXTERNAL_ID2 = 'a090t0000008E7iAAE' COMPANY_EXTERNAL_ID = 'company-external-id' USER_GITHUB_ID = 123 user = get_user_instance().get_user_by_github_id(USER_GITHUB_ID) project1 = get_project_instance().get_projects_by_external_id(PROJECT_EXTERNAL_ID1)[0] project2 = get_project_instance().get_projects_by_external_id(PROJECT_EXTERNAL_ID2)[0] company = get_company_instance().get_company_by_external_id(COMPANY_EXTERNAL_ID) # Test ICLA Agreement. sig_id = str(uuid.uuid4()) cla.log.info('Creating ICLA signature for user %s and project %s: %s' \ %(user.get_user_name(), project1.get_project_external_id(), sig_id)) signature = get_signature_instance() signature.set_signature_id(sig_id) signature.set_signature_project_id(project1.get_project_id()) signature.set_signature_signed(True) signature.set_signature_approved(True) signature.set_signature_type('cla') signature.set_signature_reference_id(user.get_user_id()) signature.set_signature_reference_type('user')
def main( aws_region, rds_database, rds_host, rds_username, rds_password, rds_port, dry_run, ): """ This script runs data migration from dynamodb to postgresql """ if os.environ.get("STAGE") is None: logger.warning( "Please set the 'STAGE' environment varaible - typically one of: {dev, staging, prod}" ) return stage = os.environ.get("STAGE") if dry_run: exit_cmd = input( "This is a dry run. " "You are running the script for the '{}' environment. " 'Press <ENTER> to continue ("exit" to exit): '.format(stage)) else: exit_cmd = input( "This is NOT a dry run. " "You are running the script for the '{}' environment. " 'Press <ENTER> to continue ("exit" to exit): '.format(stage)) if exit_cmd == "exit": return start_time = datetime.now() lock = threading.Lock() threads = [] count = 0 for _ in range(IMPORT_THREADS): connection = psycopg2.connect( database=rds_database, host=rds_host, user=rds_username, password=rds_password, port=rds_port, ) cursor = connection.cursor() worker = Thread(target=import_to_pg, args=(connection, cursor, tables_queues, dry_run)) worker.start() threads.append(worker) # TODO: cla models for signature,company-invitations and user-permissions try: user = utils.get_user_instance() company = utils.get_company_instance() project = utils.get_project_instance() repository = utils.get_repository_instance() github_orgs = utils.get_github_organization_instance() gerrit = utils.get_gerrit_instance() #signature = utils.get_signature_instance() update_queue(user.all()) update_queue(company.all()) update_queue(project.all()) #update_queue(signature.all()) update_queue(repository.all()) update_queue(gerrit.all()) update_queue(github_orgs.all()) # block until all tasks are done tables_queues.join() except Exception as err: logger.error(err) # End workers for _ in range(IMPORT_THREADS): tables_queues.put(None) for thread in threads: thread.join() duration = datetime.now() - start_time logger.info( "Data migration to the pg database run for a duration of {} ".format( duration))