def validate_sfuid_github_and_gmail(gitlab_api=None,
                                    sfuid=None,
                                    github_username=None,
                                    gdrive_api=None,
                                    gmail=None):
    """
    Verify that the given sfuid has access to gitlab, the given github_username exists and
     is in the SFU CSSS Github org and the gmail is a valid email

    Keyword Argument
    gitlab -- the gitlab api
    sfuid -- the sfuid to validate
    github_username -- the github username to validate
    gdrive_api -- the google drive api
    gmaill -- the gmail to validate

    Return
    error_message -- a list of possible error messages to display for the officer
    """
    error_messages = []
    if gitlab_api is not None:
        if sfuid is None:
            error_messages.append("No SFU ID is provided")
            logger.info(
                f"[about/officer_creation_link_management.py validate_sfuid_and_github()] {error_messages}"
            )
        else:
            success, error_message = gitlab_api.validate_username(sfuid)
            if not success:
                error_messages.append(error_message)
    if github_username is not None:
        github_api = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
        success, error_message = github_api.validate_user(github_username)
        if not success:
            error_messages.append(error_message)
        else:
            success, error_message = github_api.verify_user_in_org(
                github_username, invite_user=True)
            if not success:
                error_messages.append(error_message)
    if gdrive_api is not None:
        if gmail is None:
            error_messages.append("No Gmail is provided")
        else:
            success, file_name, error_message = gdrive_api.add_users_gdrive(
                [gmail.lower()])
            if not success:
                error_messages.append(error_message)
            else:
                gdrive_api.remove_users_gdrive([gmail.lower()])
    return error_messages
def _save_new_github_team_mapping(officer_position_names, team_name,
                                  relevant_previous_terms):
    """
    save the specified github team mapping as well as try to save all the applicable officers under that team

    Keyword Argument
    officer_position_names -- the position_name for the officer position
    team_name -- the name for the new github team

    Return
    error_messages -- the list of possible error messages
    """
    success, error_message, officer_position_mappings = \
        _get_position_mappings_assigned_to_specified_positions_names(officer_position_names)
    if not success:
        return [error_message]

    github_team = OfficerPositionGithubTeam(
        team_name=team_name, relevant_previous_terms=relevant_previous_terms)
    github_team.save()
    logger.info(
        "[about/save_new_github_officer_team_mapping.py _save_new_github_team_mapping()] "
        f"OfficerPositionGithubTeam object saved for team {team_name}")
    for position_mapping_obj in officer_position_mappings:
        OfficerPositionGithubTeamMapping(
            github_team=github_team,
            officer_position_mapping=position_mapping_obj).save()
        logger.info(
            "[about/save_new_github_officer_team_mapping.py _save_new_github_team_mapping()] "
            f"OfficerPositionGithubTeamMapping object saved for team {team_name} and officer "
            f"{position_mapping_obj}")
    github = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
    success, error_message = github.create_team(team_name)
    if not success:
        return [error_message]

    officer_github_usernames = get_list_of_officer_details_from_past_specified_terms(
        relevant_previous_terms=relevant_previous_terms,
        position_names=officer_position_names,
        filter_by_github=True)
    logger.info("[about/save_new_github_officer_team_mapping.py "
                "_save_new_github_team_mapping()] officer_github_usernames"
                f" = {officer_github_usernames}")
    error_messages = []
    for officer_github_username in officer_github_usernames:
        success, error_message = github.add_users_to_a_team(
            [officer_github_username], team_name)
        if not success:
            error_messages.append(error_message)
    return error_messages
Esempio n. 3
0
def _save_officer_github_membership(officer):
    """
    Adds the officers to the necessary github teams.

    Keyword Arguments
    officer -- the officer to add to the github teams

    return
    success -- true or false Bool
    error_message -- the error_message if success is False or None otherwise
    """
    position_mapping = OfficerEmailListAndPositionMapping.objects.all().filter(
        position_index=officer.position_index)
    if len(position_mapping) == 0:
        error_message = f"could not find any position mappings for position_index {officer.position_index}"
        logger.info(
            f"[about/officer_management_helper.py _save_officer_github_membership()] {error_message}"
        )
        return False, error_message

    github_api = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
    if github_api.connection_successful is False:
        logger.info(
            "[about/officer_management_helper.py _save_officer_github_membership()]"
            f" {github_api.error_message}")
        return False, f"{github_api.error_message}"
    github_team_mappings = OfficerPositionGithubTeamMapping.objects.all(
    ).filter(officer_position_mapping=position_mapping[0])
    for github_team_mapping in github_team_mappings:
        success, error_message = github_api.add_users_to_a_team(
            [officer.github_username],
            github_team_mapping.github_team.team_name)
        if not success:
            logger.info(
                "[about/officer_management_helper.py _save_officer_github_membership()] "
                f"unable to add officer {officer.github_username} to team"
                f" {github_team_mapping.github_team.team_name} due to error {error_message}"
            )
            return False, error_message
        logger.info(
            "[about/officer_management_helper.py _save_officer_github_membership()] "
            f"mapped officer {officer} to team {github_team_mapping.github_team.team_name}"
        )
    return True, None
def save_officer_github_membership(officer, position):
    """Adds the officers to the necessary github teams.
    they will get added both to the default GITHUB_OFFICER_TEAM
    as well as any other position specific github teams

    Keyword Arguments
    officer -- the officer to add to the github teams
    position -- the position of the officer
    """
    github = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
    if position not in OFFICERS_THAT_DO_NOT_HAVE_EYES_ONLY_PRIVILEGE:
        github.add_non_officer_to_a_team([officer.github_username], GITHUB_OFFICER_TEAM)
        OfficerGithubTeam(team_name=GITHUB_OFFICER_TEAM, officer=officer).save()
    applicable_github_teams = OfficerGithubTeamMapping.objects.filter(position=position)
    for github_team in applicable_github_teams:
        github.add_non_officer_to_a_team([officer.github_username], github_team.team_name)
        OfficerGithubTeam(team_name=github_team, officer=officer).save()
def _delete_github_mapping(post_dict):
    """
    Deletes the specific github team

    Keyword Argument
    post_dict -- the dictionary created from the POST object

    Return
    error_messages -- the list of possible error messages
    """
    if not (
            GITHUB_TEAM__ID_KEY in post_dict and f"{post_dict[GITHUB_TEAM__ID_KEY]}".isdigit() and
            len(OfficerPositionGithubTeam.objects.filter(id=int(post_dict[GITHUB_TEAM__ID_KEY]))) > 0):
        error_message = "No valid team id detected"
        logger.info("[about/update_saved_github_mappings.py _delete_github_mapping()]"
                    f" {error_message}")
        return [error_message]
    github_team_id = int(post_dict[GITHUB_TEAM__ID_KEY])
    github_mapping = OfficerPositionGithubTeam.objects.get(id=github_team_id)
    team_name = github_mapping.team_name
    github_mapping.delete()
    logger.info(f"[about/update_saved_github_mappings.py _delete_github_mapping()] deleted github team {team_name}")
    GitHubAPI(settings.GITHUB_ACCESS_TOKEN).delete_team(team_name)
    return []
def _update_github_mapping(post_dict):
    """
    Updates a github mapping. This includes its name and the officer positions assigned to it

    Keyword Argument
    post_dict -- the dictionary created from the POST object

    Return
    error_messages -- the list of possible error messages
    """
    success, error_message, officer_position_names = \
        extract_valid_officers_positions_selected_for_github_team(post_dict)
    if not success:
        logger.info(f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}")
        return [error_message]

    success, error_message = validate_position_names_for_github_team(officer_position_names)
    if not success:
        return [error_message]

    if not (GITHUB_TEAM__TEAM_NAME_KEY in post_dict):
        error_message = "No valid team name detected"
        logger.info(f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}")
        return [error_message]

    if not (
            GITHUB_TEAM__ID_KEY in post_dict and f"{post_dict[GITHUB_TEAM__ID_KEY]}".isdigit() and
            len(OfficerPositionGithubTeam.objects.all().filter(id=int(post_dict[GITHUB_TEAM__ID_KEY]))) > 0):
        error_message = "No valid team id detected"
        logger.info(f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}")
        return [error_message]

    if not (
            GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY in post_dict and
            f"{post_dict[GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY]}".lstrip('-').isdigit()
    ):
        error_message = "No valid relevant previous terms detected"
        logger.info(f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}")
        return [error_message]

    relevant_previous_terms = f"{post_dict[GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY]}"
    relevant_previous_terms = 0 - int(relevant_previous_terms.lstrip('-')) if relevant_previous_terms[0] == '-' \
        else int(relevant_previous_terms)

    if not (relevant_previous_terms >= 0):
        error_message = "No valid relevant previous terms detected"
        logger.info(f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}")
        return [error_message]

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] officer_position_names :"
        f" {officer_position_names}"
    )

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] relevant_previous_terms :"
        f" {relevant_previous_terms}"
    )
    new_github_team_name = post_dict[GITHUB_TEAM__TEAM_NAME_KEY]
    logger.info(
        f"[about/update_saved_github_mappings.py _update_github_mapping()] new_github_team_name: "
        f"{new_github_team_name}"
    )

    github_team_db_obj = OfficerPositionGithubTeam.objects.get(id=int(post_dict[GITHUB_TEAM__ID_KEY]))
    github_api = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
    if github_team_db_obj.team_name != new_github_team_name:
        success, error_message = github_api.rename_team(github_team_db_obj.team_name, new_github_team_name)
        if not success:
            return [error_message]
        github_team_db_obj.team_name = new_github_team_name
        github_team_db_obj.save()
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] github team name changed "
            f"to {new_github_team_name}"
        )

    github_usernames_that_currently_have_access = _get_github_usernames_that_currently_have_github_access(
        github_team_db_obj, github_team_db_obj.relevant_previous_terms
    )
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_that_currently_have_access: "
        f" {github_usernames_that_currently_have_access}"
    )

    if github_team_db_obj.relevant_previous_terms != relevant_previous_terms:
        github_team_db_obj.relevant_previous_terms = relevant_previous_terms
        github_team_db_obj.save()
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] github team relevant_previous_terms "
            f"changed to {relevant_previous_terms}"
        )

    github_usernames_that_need_access = _get_github_usernames_that_need_github_access_granted(
        officer_position_names, github_team_db_obj.relevant_previous_terms
    )
    logger.info(
        f"[about/update_saved_github_mappings.py _update_github_mapping()] github_usernames_that_need_access: "
        f" {github_usernames_that_need_access}"
    )

    github_usernames_need_github_access_granted = []
    github_usernames_need_github_access_revoked = []
    for github_username_that_currently_has_access in github_usernames_that_currently_have_access:
        if github_username_that_currently_has_access not in github_usernames_that_need_access:
            github_usernames_need_github_access_revoked.append(github_username_that_currently_has_access)

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_need_github_access_revoked: "
        f" {github_usernames_need_github_access_revoked}"
    )

    for github_username_that_need_access in github_usernames_that_need_access:
        if github_username_that_need_access not in github_usernames_that_currently_have_access:
            github_usernames_need_github_access_granted.append(github_username_that_need_access)
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_need_github_access_granted: "
        f" {github_usernames_need_github_access_granted}"
    )
    error_messages = []
    for github_username_need_github_access_revoked in github_usernames_need_github_access_revoked:
        success, error_message = github_api.remove_users_from_a_team([github_username_need_github_access_revoked],
                                                                     github_team_db_obj.team_name)
        if not success:
            error_messages.append(error_message)

    for github_username_need_github_access_granted in github_usernames_need_github_access_granted:
        success, error_message = github_api.add_users_to_a_team([github_username_need_github_access_granted],
                                                                github_team_db_obj.team_name)
        if not success:
            error_messages.append(error_message)

    current_officer_positions_mapped_to_github_team = [
        officer_position_github_team_mapping
        for officer_position_github_team_mapping in
        OfficerPositionGithubTeamMapping.objects.all().filter(
            github_team=github_team_db_obj
        )
    ]
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "current_officer_positions_mapped_to_github_team: "
        f" {current_officer_positions_mapped_to_github_team}"
    )
    current_officer_positions_names_mapped_to_github_team = [
        current_officer_position_mapped_to_github_team.officer_position_mapping.position_name
        for current_officer_position_mapped_to_github_team in current_officer_positions_mapped_to_github_team
    ]
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "current_officer_positions_named_mapped_to_github_team: "
        f" {current_officer_positions_names_mapped_to_github_team}"
    )
    for new_officer_position_name in officer_position_names:
        if new_officer_position_name not in current_officer_positions_names_mapped_to_github_team:
            officer_position_github_team_mapping = OfficerPositionGithubTeamMapping(
                github_team=github_team_db_obj,
                officer_position_mapping=OfficerEmailListAndPositionMapping.objects.get(
                    position_name=new_officer_position_name
                )
            )
            officer_position_github_team_mapping.save()
            logger.info(
                "[about/update_saved_github_mappings.py _update_github_mapping()] "
                "created a new officer position github team mapping: "
                f" {officer_position_github_team_mapping}"
            )
    for current_officer_position_mapped_to_github_team in current_officer_positions_mapped_to_github_team:
        if current_officer_position_mapped_to_github_team.officer_position_mapping.position_name not in \
                officer_position_names:
            logger.info(
                "[about/update_saved_github_mappings.py _update_github_mapping()] following mapping deleted "
                f" {current_officer_position_mapped_to_github_team}"
            )
            current_officer_position_mapped_to_github_team.delete()

    return error_messages
def _update_github_mapping(github_mapping):
    """
    Updates a github mapping. This includes its name and the officer positions assigned to it

    Keyword Argument
    post_dict -- the dictionary created from the POST object

    Return
    error_messages -- the list of possible error messages
    """
    if not (GITHUB_TEAM__ID_KEY in github_mapping
            and f"{github_mapping[GITHUB_TEAM__ID_KEY]}".isdigit()
            and len(OfficerPositionGithubTeam.objects.all().filter(
                id=int(github_mapping[GITHUB_TEAM__ID_KEY]))) == 1):
        error_message = "No valid team id detected"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    if not (GITHUB_TEAM__TEAM_NAME_KEY in github_mapping):
        error_message = "No valid team name detected"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    if not (GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY in github_mapping
            and f"{github_mapping[GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY]}".
            lstrip('-').isdigit()):
        error_message = "No valid relevant previous terms detected"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    if not (OFFICER_EMAIL_LIST_AND_POSITION_MAPPING__DELETE_STATUS
            in github_mapping):
        error_message = "No delete status found in request"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    if github_mapping[
            OFFICER_EMAIL_LIST_AND_POSITION_MAPPING__DELETE_STATUS] not in (
                'True', 'False'):
        error_message = "invalid delete status detected"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    if GITHUB_MAPPING_SELECTED_OFFICER_POSITIONS not in github_mapping:
        error_message = "No positions detected for github mapping"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    officer_position_names = github_mapping[
        GITHUB_MAPPING_SELECTED_OFFICER_POSITIONS]
    if type(officer_position_names) is not list:
        officer_position_names = [officer_position_names]

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] officer_position_names :"
        f" {officer_position_names}")

    success, error_message = validate_position_names_for_github_team(
        officer_position_names)
    if not success:
        return [error_message]

    delete_status = github_mapping[
        OFFICER_EMAIL_LIST_AND_POSITION_MAPPING__DELETE_STATUS] == 'True'

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] delete_status :"
        f" {delete_status}")
    relevant_previous_terms = f"{github_mapping[GITHUB_TEAM_RELEVANT_PREVIOUS_TERM_KEY]}"
    relevant_previous_terms = 0 - int(relevant_previous_terms.lstrip('-')) if relevant_previous_terms[0] == '-' \
        else int(relevant_previous_terms)

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] relevant_previous_terms :"
        f" {relevant_previous_terms}")

    if not (relevant_previous_terms >= 0):
        error_message = "No valid relevant previous terms detected"
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] {error_message}"
        )
        return [error_message]

    new_github_team_name = github_mapping[GITHUB_TEAM__TEAM_NAME_KEY]
    logger.info(
        f"[about/update_saved_github_mappings.py _update_github_mapping()] new_github_team_name: "
        f"{new_github_team_name}")

    github_team_db_obj = OfficerPositionGithubTeam.objects.get(
        id=int(github_mapping[GITHUB_TEAM__ID_KEY]))
    github_api = GitHubAPI(settings.GITHUB_ACCESS_TOKEN)
    if github_mapping[DELETE_GITHUB_MAPPING] == 'True':
        return [_delete_github_mapping(github_team_db_obj, github_api)]

    if github_team_db_obj.team_name != new_github_team_name:
        success, error_message = github_api.rename_team(
            github_team_db_obj.team_name, new_github_team_name)
        if not success:
            return [error_message]
        github_team_db_obj.team_name = new_github_team_name
        github_team_db_obj.save()
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] github team name changed "
            f"to {new_github_team_name}")
    if github_team_db_obj.marked_for_deletion != delete_status:
        github_team_db_obj.marked_for_deletion = delete_status
        github_team_db_obj.save()

    github_usernames_that_currently_have_access = _get_github_usernames_that_currently_have_github_access(
        github_team_db_obj, github_team_db_obj.relevant_previous_terms)
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_that_currently_have_access: "
        f" {github_usernames_that_currently_have_access}")

    if github_team_db_obj.relevant_previous_terms != relevant_previous_terms:
        github_team_db_obj.relevant_previous_terms = relevant_previous_terms
        github_team_db_obj.save()
        logger.info(
            f"[about/update_saved_github_mappings.py _update_github_mapping()] github team relevant_previous_terms "
            f"changed to {relevant_previous_terms}")

    github_usernames_that_need_access = _get_github_usernames_that_need_github_access_granted(
        officer_position_names, github_team_db_obj.relevant_previous_terms)
    logger.info(
        f"[about/update_saved_github_mappings.py _update_github_mapping()] github_usernames_that_need_access: "
        f" {github_usernames_that_need_access}")

    github_usernames_need_github_access_granted = []
    github_usernames_need_github_access_revoked = []
    for github_username_that_currently_has_access in github_usernames_that_currently_have_access:
        if github_username_that_currently_has_access not in github_usernames_that_need_access:
            github_usernames_need_github_access_revoked.append(
                github_username_that_currently_has_access)

    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_need_github_access_revoked: "
        f" {github_usernames_need_github_access_revoked}")

    for github_username_that_need_access in github_usernames_that_need_access:
        if github_username_that_need_access not in github_usernames_that_currently_have_access:
            github_usernames_need_github_access_granted.append(
                github_username_that_need_access)
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "github_usernames_need_github_access_granted: "
        f" {github_usernames_need_github_access_granted}")
    error_messages = []
    for github_username_need_github_access_revoked in github_usernames_need_github_access_revoked:
        success, error_message = github_api.remove_users_from_a_team(
            [github_username_need_github_access_revoked],
            github_team_db_obj.team_name)
        if not success:
            error_messages.append(error_message)

    for github_username_need_github_access_granted in github_usernames_need_github_access_granted:
        success, error_message = github_api.add_users_to_a_team(
            [github_username_need_github_access_granted],
            github_team_db_obj.team_name)
        if not success:
            error_messages.append(error_message)

    current_officer_positions_mapped_to_github_team = [
        officer_position_github_team_mapping
        for officer_position_github_team_mapping in
        OfficerPositionGithubTeamMapping.objects.all().filter(
            github_team=github_team_db_obj)
    ]
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "current_officer_positions_mapped_to_github_team: "
        f" {current_officer_positions_mapped_to_github_team}")
    current_officer_positions_names_mapped_to_github_team = [
        current_officer_position_mapped_to_github_team.
        officer_position_mapping.position_name
        for current_officer_position_mapped_to_github_team in
        current_officer_positions_mapped_to_github_team
    ]
    logger.info(
        "[about/update_saved_github_mappings.py _update_github_mapping()] "
        "current_officer_positions_named_mapped_to_github_team: "
        f" {current_officer_positions_names_mapped_to_github_team}")
    for new_officer_position_name in officer_position_names:
        if new_officer_position_name not in current_officer_positions_names_mapped_to_github_team:
            officer_position_github_team_mapping = OfficerPositionGithubTeamMapping(
                github_team=github_team_db_obj,
                officer_position_mapping=OfficerEmailListAndPositionMapping.
                objects.get(position_name=new_officer_position_name))
            officer_position_github_team_mapping.save()
            logger.info(
                "[about/update_saved_github_mappings.py _update_github_mapping()] "
                "created a new officer position github team mapping: "
                f" {officer_position_github_team_mapping}")
    for current_officer_position_mapped_to_github_team in current_officer_positions_mapped_to_github_team:
        if current_officer_position_mapped_to_github_team.officer_position_mapping.position_name not in \
                officer_position_names:
            logger.info(
                "[about/update_saved_github_mappings.py _update_github_mapping()] following mapping deleted "
                f" {current_officer_position_mapped_to_github_team}")
            current_officer_position_mapped_to_github_team.delete()

    return error_messages