Exemplo n.º 1
0
def group_snapshot_by_group_name_get(team_name: str,
                                     group_name: str) -> Response:
    """
    Get a snapshot about a group based on the group name.
    :param team_name: Unique name which identifies a team.
    :param group_name: Unique name which identifies a group within a team.
    :return: A response object for the GET API request.
    """
    group_row: Optional[RowProxy] = GroupDao.get_group(team_name=team_name,
                                                       group_name=group_name)

    if group_row is None:
        response = jsonify({
            'self': f'/v2/groups/snapshot/{team_name}/{group_name}',
            'group': f'/v2/groups/{team_name}/{group_name}',
            'group_snapshot': None,
            'error': 'the group does not exist'
        })
        response.status_code = 400
        return response

    group_dict = {key: value for key, value in group_row.items()}
    group = Group(group_dict)

    group_members: ResultProxy = GroupMemberDao.get_group_members(
        group_name=group_name, team_name=team_name)
    group_members_list = [{
        'username': member.username,
        'first': member.first,
        'last': member.last,
        'member_since': member.member_since,
        'user': member.user,
        'status': member.status
    } for member in group_members]

    # All group statistics are queried separately but combined into a single map
    statistics = compile_group_statistics(group_object=group)

    group_dict: dict = GroupData(group).__dict__

    try:
        group_dict['grouppic'] = group_dict['grouppic'].decode('utf-8')
    except AttributeError:
        pass

    group_dict['members'] = group_members_list
    group_dict['statistics'] = statistics

    response = jsonify({
        'self': f'/v2/groups/snapshot/{team_name}/{group_name}',
        'group': f'/v2/groups/{team_name}/{group_name}',
        'group_snapshot': group_dict
    })
    response.status_code = 200
    return response
Exemplo n.º 2
0
def group_members_by_group_name_get(team_name: str,
                                    group_name: str) -> Response:
    """
    Get the members of a group based on the group name.
    :param team_name: Unique name which identifies a team.
    :param group_name: Unique name which identifies a group within a team.
    :return: A response object for the GET API request.
    """
    group_members: ResultProxy = GroupMemberDao.get_group_members(
        group_name=group_name, team_name=team_name)

    if group_members is None or group_members.rowcount == 0:
        response = jsonify({
            'self':
            f'/v2/groups/members/{team_name}/{group_name}',
            'group':
            f'/v2/groups/{team_name}/{group_name}',
            'group_members':
            None,
            'error':
            'the group does not exist or there are no members in the group'
        })
        response.status_code = 400
        return response
    else:
        group_members_list = [{
            'username': member.username,
            'first': member.first,
            'last': member.last,
            'member_since': member.member_since,
            'user': member.user,
            'status': member.status
        } for member in group_members]

        response = jsonify({
            'self': f'/v2/groups/members/{team_name}/{group_name}',
            'group': f'/v2/groups/{team_name}/{group_name}',
            'group_members': group_members_list
        })
        response.status_code = 200
        return response
Exemplo n.º 3
0
def group_members_by_id_get(group_id: str) -> Response:
    """
    Get the members of a group based on the group id.
    :param group_id: Unique id which identifies a group.
    :return: A response object for the GET API request.
    """
    group_members: ResultProxy = GroupMemberDao.get_group_members_by_id(
        group_id=group_id)

    if group_members is None or group_members.rowcount == 0:
        response = jsonify({
            'self':
            f'/v2/groups/members/{group_id}',
            'group':
            f'/v2/groups/{group_id}',
            'group_members':
            None,
            'error':
            'a group does not exist with this id or the group has no members'
        })
        response.status_code = 400
        return response
    else:
        group_members_list = [{
            'username': member.username,
            'first': member.first,
            'last': member.last,
            'member_since': member.member_since,
            'user': member.user,
            'status': member.status
        } for member in group_members]

        response = jsonify({
            'self': f'/v2/groups/members/{group_id}',
            'group': f'/v2/groups/{group_id}',
            'group_members': group_members_list
        })
        response.status_code = 200
        return response
Exemplo n.º 4
0
def user_memberships_by_username_get(username) -> Response:
    """
    Get the team and group memberships for a user.
    :param username: Username that uniquely identifies a user.
    :return: A response object for the GET API request.
    """
    teams: ResultProxy = TeamMemberDao.get_user_teams(username=username)
    membership_list = []

    for team in teams:
        groups: ResultProxy = GroupMemberDao.get_user_groups_in_team(
            username=username, team_name=team['team_name'])
        membership_list.append({
            'team_name':
            team['team_name'],
            'title':
            team['title'],
            'status':
            team['status'],
            'user':
            team['user'],
            'groups': [{
                'group_name': group['group_name'],
                'group_title': group['group_title'],
                'group_id': group['group_id'],
                'status': group['status'],
                'user': group['user']
            } for group in groups]
        })

    response = jsonify({
        'self': f'/v2/users/memberships/{username}',
        'memberships': membership_list
    })
    response.status_code = 200
    return response
Exemplo n.º 5
0
def user_groups_by_username_get(username) -> Response:
    """
    Get the group memberships for a user.
    :param username: Username that uniquely identifies a user.
    :return: A response object for the GET API request.
    """
    groups: ResultProxy = GroupMemberDao.get_user_groups(username=username)
    group_list = []

    for group in groups:
        group_list.append({
            'id': group['id'],
            'group_name': group['group_name'],
            'group_title': group['group_title'],
            'status': group['status'],
            'user': group['user']
        })

    response = jsonify({
        'self': f'/v2/users/groups/{username}',
        'groups': group_list
    })
    response.status_code = 200
    return response
Exemplo n.º 6
0
def user_snapshot_by_username_get(username) -> Response:
    """
    Get a snapshot with information about a user with a given username.
    :param username: Username that uniquely identifies a user.
    :return: A response object for the GET API request.
    """
    user: User = UserDao.get_user_by_username(username=username)

    # If the user cant be found, try searching the email column in the database
    if user is None:
        email = username
        user: User = UserDao.get_user_by_email(email=email)

    # If the user still can't be found, return with an error code
    if user is None:
        response = jsonify({
            'self': f'/v2/users/snapshot/{username}',
            'user': None,
            'error': 'there is no user with this username'
        })
        response.status_code = 400
        return response
    else:
        user_dict: dict = UserData(user).__dict__

        if user_dict.get('member_since') is not None:
            user_dict['member_since'] = str(user_dict['member_since'])
        if user_dict.get('last_signin') is not None:
            user_dict['last_signin'] = str(user_dict['last_signin'])

        if user_dict.get('profilepic') is not None:
            try:
                user_dict['profilepic'] = user_dict['profilepic'].decode(
                    'utf-8')
            except AttributeError:
                pass

        username = user_dict['username']
        groups: ResultProxy = GroupMemberDao.get_user_groups(username=username)
        group_list = []

        for group in groups:
            group_dict = {
                'id': group['id'],
                'group_name': group['group_name'],
                'group_title': group['group_title'],
                'status': group['status'],
                'user': group['user']
            }
            newest_log: Column = GroupDao.get_newest_log_date(
                group['group_name'])
            group_dict['newest_log'] = newest_log['newest']

            newest_message = GroupDao.get_newest_message_date(
                group['group_name'])
            group_dict['newest_message'] = newest_message['newest']

            group_list.append(group_dict)

        user_dict['groups'] = group_list

        forgot_password_codes: ResultProxy = ForgotPasswordDao.get_forgot_password_codes(
            username=username)

        forgot_password_list = []
        for forgot_password_code in forgot_password_codes:
            forgot_password_list.append({
                'forgot_code':
                forgot_password_code['forgot_code'],
                'username':
                forgot_password_code['username'],
                'expires':
                forgot_password_code['expires'],
                'deleted':
                forgot_password_code['deleted'],
            })

        user_dict['forgotpassword'] = forgot_password_list

        flairs: List[Flair] = FlairDao.get_flair_by_username(username=username)
        flair_dicts = []

        for flair in flairs:
            flair_dicts.append(FlairData(flair).__dict__)

        user_dict['flair'] = flair_dicts

        notifications: ResultProxy = NotificationDao.get_notification_by_username(
            username=username)

        notification_dicts = []
        for notification in notifications:
            notification_dicts.append({
                'notification_id':
                notification['notification_id'],
                'username':
                notification['username'],
                'time':
                notification['time'],
                'link':
                notification['link'],
                'viewed':
                notification['viewed'],
                'description':
                notification['description']
            })

        user_dict['notifications'] = notification_dicts

        stats = compile_user_statistics(user, username)
        user_dict['statistics'] = stats

        response = jsonify({
            'self': f'/v2/users/snapshot/{username}',
            'user': user_dict
        })
        response.status_code = 200
        return response
Exemplo n.º 7
0
def group_members_by_group_id_and_username_delete(group_id: str,
                                                  username: str) -> Response:
    """
    Soft delete a group membership.  The membership is identified by a group's identifier and a user's username.
    :param group_id: Unique id which identifies a group within a team.
    :param username: Unique name for a user.
    :return: A response object for the DELETE API request.
    """
    jwt_claims: dict = get_claims(request)
    jwt_username = jwt_claims.get('sub')

    group_member: GroupMember = GroupMemberDao.get_group_member(
        group_id=int(group_id), username=jwt_username)

    if group_member is not None and group_member.user == 'admin' and group_member.status == 'accepted':
        current_app.logger.info(
            f'Admin user {jwt_username} is deleting the group membership for user {username} in group with id '
            f'{group_id}.')
    else:
        current_app.logger.info(
            f'User {jwt_username} is not authorized to delete the group membership for user {username} in group with '
            f'id {group_id}.')
        response = jsonify({
            'self':
            f'/v2/groups/members/{group_id}/{username}',
            'deleted':
            False,
            'error':
            f'User {jwt_username} is not authorized to delete the group membership for user {username} in '
            f'group with id {group_id}.'
        })
        response.status_code = 400
        return response

    membership_deleted = GroupMemberDao.soft_delete_group_member(
        int(group_id), username)

    if membership_deleted:
        team: Team = TeamDao.get_team_by_group_id(int(group_id))
        user_groups: ResultProxy = GroupMemberDao.get_user_groups_in_team(
            username, team.name)

        # If the user has no more group memberships in this team, remove them from the team.
        if user_groups.rowcount == 0:
            TeamMemberDao.update_user_memberships(username=username,
                                                  teams_joined=[],
                                                  teams_left=[team.name],
                                                  groups_joined=[],
                                                  groups_left=[])

        response = jsonify({
            'self': f'/v2/groups/members/{group_id}/{username}',
            'deleted': True,
        })
        response.status_code = 204
        return response
    else:
        response = jsonify({
            'self': f'/v2/groups/members/{group_id}/{username}',
            'deleted': False,
            'error': 'Failed to delete the group membership.'
        })
        response.status_code = 500
        return response
Exemplo n.º 8
0
def group_members_by_group_id_and_username_put(group_id: str,
                                               username: str) -> Response:
    """
    Update a group membership.  The membership is identified by a group's identifier and a user's username.
    :param group_id: Unique id which identifies a group within a team.
    :param username: Unique name for a user.
    :return: A response object for the PUT API request.
    """
    jwt_claims: dict = get_claims(request)
    jwt_username = jwt_claims.get('sub')

    group_member: GroupMember = GroupMemberDao.get_group_member(
        group_id=int(group_id), username=jwt_username)

    if group_member is not None and group_member.user == 'admin' and group_member.status == 'accepted':
        current_app.logger.info(
            f'Admin user {jwt_username} is updating the group membership for user {username} in group with id '
            f'{group_id}.')
    else:
        current_app.logger.info(
            f'User {jwt_username} is not authorized to update the group membership for user {username} in group with '
            f'id {group_id}.')
        response = jsonify({
            'self':
            f'/v2/groups/members/{group_id}/{username}',
            'updated':
            False,
            'group_member':
            None,
            'error':
            f'User {jwt_username} is not authorized to update the group membership for user {username} in '
            f'group with id {group_id}.'
        })
        response.status_code = 400
        return response

    group_member_data: dict = request.get_json()
    status = group_member_data.get('status')
    user = group_member_data.get('user')

    is_updated = GroupMemberDao.update_group_member(int(group_id), username,
                                                    status, user)

    if is_updated:
        team: Team = TeamDao.get_team_by_group_id(int(group_id))
        team_membership: ResultProxy = TeamMemberDao.get_user_team_membership(
            username=username, team_name=team.name)

        if team_membership.rowcount > 0:
            for membership in team_membership:
                if membership.user != 'accepted':
                    TeamMemberDao.accept_user_team_membership(
                        username=username,
                        team_name=team.name,
                        updating_username=jwt_username)

        updated_group_member = GroupMemberDao.get_group_member(
            int(group_id), username)
        updated_group_member_dict: dict = GroupMemberData(
            updated_group_member).__dict__

        response = jsonify({
            'self': f'/v2/groups/members/{group_id}/{username}',
            'updated': True,
            'group_member': updated_group_member_dict
        })
        response.status_code = 200
        return response
    else:
        response = jsonify({
            'self': f'/v2/groups/members/{group_id}/{username}',
            'updated': False,
            'group_member': None,
            'error': 'The group membership failed to update.'
        })
        response.status_code = 500
        return response
Exemplo n.º 9
0
def group_by_id_put(group_id: str) -> Response:
    """
    Update a group based on the unique group id.
    :param group_id: Unique id which identifies a group.
    :return: A response object for the PUT API request.
    """
    old_group = GroupDao.get_group_by_id(int(group_id))

    jwt_claims: dict = get_claims(request)
    jwt_username = jwt_claims.get('sub')

    group_member: GroupMember = GroupMemberDao.get_group_member(
        group_id=int(group_id), username=jwt_username)

    if group_member is not None and group_member.user == 'admin' and group_member.status == 'accepted':
        current_app.logger.info(
            f'Admin user {jwt_username} is updating a group with id {group_id}.'
        )
    else:
        current_app.logger.info(
            f'User {jwt_username} is not authorized to update a group with id {group_id}.'
        )
        response = jsonify({
            'self':
            f'/v2/groups/{group_id}',
            'updated':
            False,
            'group':
            None,
            'error':
            f'User {jwt_username} is not authorized to update a group with id {group_id}.'
        })
        response.status_code = 400
        return response

    if old_group is None:
        response = jsonify({
            'self': f'/v2/groups/{group_id}',
            'updated': False,
            'group': None,
            'error': 'There is no existing group with this id.'
        })
        response.status_code = 400
        return response

    group_data: dict = request.get_json()
    new_group = Group(group_data)

    if new_group != old_group:
        new_group.modified_date = datetime.now()
        new_group.modified_app = 'saints-xctf-api'

        is_updated = GroupDao.update_group(group=new_group)

        if is_updated:
            updated_group = GroupDao.get_group_by_id(int(group_id))
            updated_group_dict: dict = GroupData(updated_group).__dict__

            response = jsonify({
                'self': f'/v2/groups/{group_id}',
                'updated': True,
                'group': updated_group_dict
            })
            response.status_code = 200
            return response
        else:
            response = jsonify({
                'self': f'/v2/groups/{group_id}',
                'updated': False,
                'group': None,
                'error': 'The group failed to update.'
            })
            response.status_code = 500
            return response
    else:
        response = jsonify({
            'self':
            f'/v2/groups/{group_id}',
            'updated':
            False,
            'group':
            None,
            'error':
            'The group submitted is equal to the existing group with the same id.'
        })
        response.status_code = 400
        return response
Exemplo n.º 10
0
def group_by_group_name_put(team_name: str, group_name: str) -> Response:
    """
    Update a group in the database.
    :param team_name: Unique name which identifies a team.
    :param group_name: Unique name which identifies a group within a team.
    :return: A response object for the PUT API request.
    """
    old_group_row: Optional[RowProxy] = GroupDao.get_group(
        team_name=team_name, group_name=group_name)

    if old_group_row is None:
        response = jsonify({
            'self': f'/v2/groups/{team_name}/{group_name}',
            'updated': False,
            'group': None,
            'error': 'there is no existing group with this name'
        })
        response.status_code = 400
        return response

    jwt_claims: dict = get_claims(request)
    jwt_username = jwt_claims.get('sub')

    group_member: GroupMember = GroupMemberDao.get_group_member_by_group_name(
        team_name=team_name, group_name=group_name, username=jwt_username)

    if group_member is not None and group_member.user == 'admin' and group_member.status == 'accepted':
        current_app.logger.info(
            f'Admin user {jwt_username} is updating a group with name {group_name} in team {team_name}.'
        )
    else:
        current_app.logger.info(
            f'User {jwt_username} is not authorized to update a group with name {group_name} in team {team_name}.'
        )
        response = jsonify({
            'self':
            f'/v2/groups/{team_name}/{group_name}',
            'updated':
            False,
            'group':
            None,
            'error':
            f'User {jwt_username} is not authorized to update a group with name {group_name} in team '
            f'{team_name}.'
        })
        response.status_code = 400
        return response

    old_group_dict = {key: value for key, value in old_group_row.items()}
    old_group = Group(old_group_dict)
    group_data: dict = request.get_json()
    new_group = Group(group_data)

    if old_group != new_group:

        new_group.modified_date = datetime.now()
        new_group.modified_app = 'saints-xctf-api'

        is_updated = GroupDao.update_group(group=new_group)

        if is_updated:
            updated_group_row: Optional[RowProxy] = GroupDao.get_group(
                team_name=team_name, group_name=new_group.group_name)

            updated_group_dict = {
                key: value
                for key, value in updated_group_row.items()
            }
            response = jsonify({
                'self': f'/v2/groups/{team_name}/{group_name}',
                'updated': True,
                'group': updated_group_dict
            })
            response.status_code = 200
            return response
        else:
            response = jsonify({
                'self': f'/v2/groups/{team_name}/{group_name}',
                'updated': False,
                'group': None,
                'error': 'the group failed to update'
            })
            response.status_code = 500
            return response
    else:
        response = jsonify({
            'self':
            f'/v2/groups/{team_name}/{group_name}',
            'updated':
            False,
            'group':
            None,
            'error':
            'the group submitted is equal to the existing group with the same name'
        })
        response.status_code = 400
        return response