예제 #1
0
파일: docker.py 프로젝트: tefah/picoCTF
    def put(self, digest, container_id):
        """
        Reset (delete and start) a running DockerContainer instance
        """

        # Containers are mapped to teams
        user_account = api.user.get_user()
        tid = user_account['tid']


        # fail fast on invalid requests
        if any(char not in string.hexdigits for char in container_id):
            raise PicoException("Invalid container ID", 400)
        if any(char not in string.hexdigits + "sha:" for char in digest):
            raise PicoException("Invalid image digest", 400)

        # Delete the container
        del_result = api.docker.delete(container_id)

        # Create the container
        create_result = api.docker.create(tid, digest)

        if del_result and create_result["success"]:
            return jsonify({"success": True,
                "message": "Challenge reset.\nBe sure to use the new port."})
        else:
            return jsonify({"success": False, "message": "Error resetting challenge"})
예제 #2
0
    def post(self):
        """Create and automatically join new team."""
        req = team_req.parse_args(strict=True)
        curr_user = api.user.get_user()
        if curr_user['teacher']:
            raise PicoException('Teachers may not create teams', 403)
        req['team_name'] = req['team_name'].strip()
        if not all([
                c in string.digits + string.ascii_lowercase + " ()+-,#'&!?"
                for c in req['team_name'].lower()
        ]):
            raise PicoException(
                "Team names cannot contain special characters other than " +
                "()+-,#'&!?",
                status_code=400)

        if req['team_name'] == curr_user['username']:
            raise PicoException("Invalid team name", status_code=409)

        new_tid = api.team.create_and_join_new_team(req['team_name'],
                                                    req['team_password'],
                                                    curr_user)
        res = jsonify({'success': True, 'tid': new_tid})
        res.status_code = 201
        return res
예제 #3
0
    def post(self, group_id):
        """
        Elevate a specified team within a group to the teacher role.

        Requires teacher role within the group.
        """
        req = group_modify_team_req.parse_args(strict=True)
        group = api.group.get_group(group_id)
        if not group:
            raise PicoException('Classroom not found', 404)
        group_teachers = [group['owner']] + group['teachers']
        eligible_for_elevation = group['members']
        curr_tid = api.user.get_user()['tid']

        # Ensure the current user has a teacher role within the group
        if curr_tid not in group_teachers:
            raise PicoException(
                'You must be a teacher in this classroom to remove a team.',
                status_code=403
            )

        # Ensure the specified tid is eligible for elevation
        if req['team_id'] not in eligible_for_elevation:
            raise PicoException(
                'Team is not eligible for elevation to teacher role',
                status_code=422
            )

        api.group.elevate_team(group_id, req['team_id'])
        return jsonify({
            'success': True
        })
예제 #4
0
    def get(self, group_id):
        """Retrieve a scoreboard page for a group."""
        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException('Classroom not found', 404)
        group_members = [group['owner']] + group['members'] + group['teachers']

        curr_user = api.user.get_user()
        if (not curr_user or (curr_user['tid'] not in group_members
                              and not curr_user['admin'])):
            raise PicoException("You do not have permission to " +
                                "view this classroom's scoreboard.", 403)

        req = scoreboard_page_req.parse_args(strict=True)
        if req['search'] is not None:
            page = api.stats.get_filtered_scoreboard_page(
                {'group_id': group_id},
                req['search'], req['page'] or 1
            )
        else:
            page = api.stats.get_scoreboard_page(
                {'group_id': group_id}, req['page'])
        return jsonify({
            'scoreboard': page[0],
            'current_page': page[1],
            'total_pages': page[2]
        })
예제 #5
0
    def post(self, group_id):
        """
        Remove a specified team from a group.

        Requires teacher role within the group.
        """
        req = group_remove_team_req.parse_args(strict=True)
        group = api.group.get_group(group_id)
        if not group:
            raise PicoException('Group not found', 404)
        group_teachers = [group['owner']] + group['teachers']
        eligible_for_removal = group['members'] + group['teachers']
        curr_tid = api.user.get_user()['tid']

        # Ensure the user has a teacher role within the group
        if curr_tid not in group_teachers:
            raise PicoException(
                'You must be a teacher in this group to remove a team.',
                status_code=403)

        # Ensure the specified tid is a member of the group
        if req['team_id'] not in eligible_for_removal:
            raise PicoException(
                'Specified team is not eligible for removal from this group',
                status_code=422)

        api.group.leave_group(group_id, req['team_id'])
        return jsonify({'success': True})
예제 #6
0
    def get(self, problem_id):
        """Retrieve a specific problem."""
        # Ensure that the problem exists
        problem = api.problem.get_problem(problem_id)
        if not problem:
            raise PicoException("Problem not found", status_code=404)

        # Add synthetic fields
        curr_user = api.user.get_user()
        problem["solves"] = api.stats.get_problem_solves(problem["pid"])
        problem["unlocked"] = problem["pid"] in api.problem.get_unlocked_pids(
            curr_user["tid"])
        problem["solved"] = problem["pid"] in api.problem.get_solved_pids(
            tid=curr_user["tid"])
        if curr_user.get("admin", False):
            problem["reviews"] = api.problem_feedback.get_problem_feedback(
                pid=problem["pid"], count_only=True)

        # Ensure that the user has unlocked it
        if not problem["unlocked"]:
            raise PicoException("You have not unlocked this problem", 403)

        # Strip out instance and system info if not admin
        curr_user = api.user.get_user()
        if not curr_user.get("admin", False):
            problem = api.problem.filter_problem_instances(
                problem, curr_user["tid"])
            problem = api.problem.sanitize_problem_data(problem)

        return jsonify(problem)
예제 #7
0
파일: user.py 프로젝트: 6r0k3d/picoCTF
def set_htb_id(user_name, htb_id):
    """
    Note: This could be done with def update_extdata, however
    update_extdata looks up the logged in user. This request
    is being performed by a challenge at the request of a user,
    so the user lookup there would fail.

    Associate a users Hack the Box ID with their User data.

    Args:
        user_name: the user who's profile is updated
        htb_id: the HTB id for the user
    """
    user = get_user(name=user_name)

    if not user:
        raise PicoException("Could not find user", 400)

    if "htb_id" in user:
        raise PicoException("HTB ID already set", 409)

    users = get_all_users()
    for u in users:
        if "htb_id" in u:
            if htb_id == u["htb_id"]:
                raise PicoException("Another User has this HTB ID already",
                                    409)

    db = api.db.get_conn()
    db.users.update_one({"uid": user["uid"]}, {"$set": {"htb_id": htb_id}})

    return {"success": True}
예제 #8
0
    def get(self, problem_id):
        """Retrieve a specific problem."""
        # Ensure that the problem exists
        problem = api.problem.get_problem(problem_id)
        if not problem:
            raise PicoException('Problem not found', status_code=404)

        # Add synthetic fields
        curr_user = api.user.get_user()
        problem['solves'] = api.stats.get_problem_solves(problem['pid'])
        problem['unlocked'] = \
            problem['pid'] in api.problem.get_unlocked_pids(
                curr_user['tid'])
        problem['solved'] = \
            problem['pid'] in api.problem.get_solved_pids(curr_user['tid'])
        if curr_user.get('admin', False):
            problem['reviews'] = api.problem_feedback.get_problem_feedback(
                pid=problem['pid'])

        # Ensure that the user has unlocked it
        if not problem['unlocked']:
            raise PicoException('You have not unlocked this problem', 403)

        # Strip out instance and system info if not admin
        curr_user = api.user.get_user()
        if not curr_user.get('admin', False):
            problem = api.problem.filter_problem_instances(
                problem, curr_user['tid'])
            problem = api.problem.sanitize_problem_data(problem)

        return jsonify(problem)
예제 #9
0
파일: groups.py 프로젝트: syclops/ctflab
    def get(self, group_id):
        """Retrieve a scoreboard page for a group."""
        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException("Classroom not found", 404)
        group_members = [group["owner"]] + group["members"] + group["teachers"]

        curr_user = api.user.get_user()
        if not curr_user or (curr_user["tid"] not in group_members
                             and not curr_user["admin"]):
            raise PicoException(
                "You do not have permission to " +
                "view this classroom's scoreboard.",
                403,
            )

        req = scoreboard_page_req.parse_args(strict=True)
        if req["search"] is not None:
            page = api.stats.get_filtered_scoreboard_page(
                {"group_id": group_id}, req["search"], req["page"] or 1)
        else:
            page = api.stats.get_scoreboard_page({"group_id": group_id},
                                                 req["page"])
        return jsonify({
            "scoreboard": page[0],
            "current_page": page[1],
            "total_pages": page[2]
        })
예제 #10
0
파일: groups.py 프로젝트: syclops/ctflab
    def post(self, group_id):
        """
        Remove a specified team from a group.

        Requires teacher role within the group.
        """
        req = group_modify_team_req.parse_args(strict=True)
        group = api.group.get_group(group_id)
        if not group:
            raise PicoException("Classroom not found", 404)
        group_teachers = [group["owner"]] + group["teachers"]
        eligible_for_removal = group["members"] + group["teachers"]
        curr_tid = api.user.get_user()["tid"]

        # Ensure the user has a teacher role within the group
        if curr_tid not in group_teachers:
            raise PicoException(
                "You must be a teacher in this classroom to remove a team.",
                status_code=403,
            )

        # Ensure the specified tid is a member of the group
        if req["team_id"] not in eligible_for_removal:
            raise PicoException(
                "Team is not eligible for removal from this classroom",
                status_code=422)

        api.group.leave_group(group_id, req["team_id"])
        return jsonify({"success": True})
예제 #11
0
def update_password_request(params):
    """
    Update team password.

    Assumes args are keys in params.

    Args:
        params:
            new-password: the new password
            new-password-confirmation: confirmation of password
    """
    user = api.user.get_user()
    current_team = api.team.get_team(tid=user["tid"])
    if current_team["team_name"] == user["username"]:
        raise PicoException("You have not created a team yet.", 422)

    if params["new-password"] != params["new-password-confirmation"]:
        raise PicoException("Your team passwords do not match.", 422)

    db = api.db.get_conn()
    db.teams.update({'tid': user['tid']}, {
        '$set': {
            'password': api.common.hash_password(params["new-password"])
        }
    })
예제 #12
0
파일: user.py 프로젝트: materaj2/picoCTF
def update_password_request(params, uid=None, check_current=False):
    """
    Update account password.

    Assumes args are keys in params.

    Args:
        uid: uid to reset
        check_current: whether to ensure that current-password is correct
        params (dict):
            current-password: the users current password
            new-password: the new password
            new-password-confirmation: confirmation of password
    """
    user = get_user(uid=uid, include_pw_hash=True)

    if check_current and not api.user.confirm_password(
            params["current-password"], user['password_hash']):
        raise PicoException("Your current password is incorrect.", 422)

    if params["new-password"] != params["new-password-confirmation"]:
        raise PicoException("Your passwords do not match.", 422)

    db = api.db.get_conn()
    db.users.update({'uid': user['uid']}, {
        '$set': {
            'password_hash': api.common.hash_password(params["new-password"])
        }
    })
예제 #13
0
파일: team.py 프로젝트: syclops/ctflab
def remove_member(tid, uid):
    """
    Move the specified member back to their self-team.

    Eliminates custom team if no members remain.
    The member specified cannot have submitted any valid solutions.
    """
    team = get_team(tid)
    curr_user_uid = api.user.get_user()["uid"]
    curr_user_is_creator = curr_user_uid == team.get("creator")

    if not curr_user_is_creator and uid != curr_user_uid:
        raise PicoException("Only the team captain can kick other members.",
                            status_code=403)

    if uid not in get_team_uids(tid):
        raise PicoException("Specified user is not a member of this team.",
                            status_code=404)

    if api.user.get_user(uid=uid)["username"] == team["team_name"]:
        raise PicoException("Cannot remove self from default team",
                            status_code=403)

    if not api.user.can_leave_team(uid):
        if curr_user_is_creator and curr_user_uid == uid:
            raise PicoException(
                "Team captain must be the only remaining member in order " +
                "to leave.",
                status_code=403,
            )
        else:
            raise PicoException(
                "This team member has submitted a flag and can no longer " +
                "be removed.",
                status_code=403,
            )

    self_team_tid = api.team.get_team(name=api.user.get_user(
        uid=uid)["username"])["tid"]

    db = api.db.get_conn()
    db.users.find_one_and_update({"uid": uid},
                                 {"$set": {
                                     "tid": self_team_tid
                                 }})

    db.teams.find_one_and_update({"tid": self_team_tid}, {"$inc": {"size": 1}})

    db.teams.find_one_and_update({"tid": tid}, {"$inc": {"size": -1}})

    # Delete the custom team if no members remain
    remaining_team_size = db.teams.find_one({"tid": tid}, {"size": 1})["size"]
    if remaining_team_size < 1:
        delete_team(tid)

    # Copy any acquired group memberships back to the self-team
    for group in get_groups(tid):
        api.group.join_group(gid=group["gid"], tid=self_team_tid)
예제 #14
0
파일: team.py 프로젝트: syclops/ctflab
def create_and_join_new_team(team_name, team_password, user):
    """
    Fulfill new team requests for users who have already registered.

    Seperate from create_team() as we need to do additional logic:
    - Check that the new team name doesn't conflict with a team or user
    - Check that the user creating the team is on their initial
      1-person "username team"

    Args:
        team_name: The desired name for the team.
                   Must be unique across users and teams.
        team_password: The team's password.
        user: The user

    Returns:
        The tid of the new team

    Raises:
        PicoException if a team or user with name team_name already exists,
                      or if user has already created a team

    """
    # Ensure name does not conflict with existing user or team
    db = api.db.get_conn()
    if db.users.find_one(
        {"username": team_name},
            collation=Collation(locale="en",
                                strength=CollationStrength.PRIMARY),
    ):
        raise PicoException("There is already a user with this name.", 409)
    if db.teams.find_one(
        {"team_name": team_name},
            collation=Collation(locale="en",
                                strength=CollationStrength.PRIMARY),
    ):
        raise PicoException("There is already a team with this name.", 409)

    # Make sure the creating user has not already created a team
    current_team = api.team.get_team(tid=user["tid"])
    if current_team["team_name"] != user["username"]:
        raise PicoException(
            "You can only create one new team per user account!", 422)

    # Create the team and join it
    new_tid = create_team({
        "team_name": team_name,
        "password": api.common.hash_password(team_password),
        "affiliation": current_team["affiliation"],
        "creator": user["uid"],
        "allow_ineligible_members": False,
    })
    join_team(team_name, team_password, user)

    return new_tid
예제 #15
0
파일: user.py 프로젝트: materaj2/picoCTF
 def wrapper(*args, **kwds):
     if 'token' not in session:
         raise PicoException(
             'Internal server error',
             data={'debug': 'CSRF token not found in session'})
     submitted_token = request.headers.get('X-CSRF-Token', None)
     if submitted_token is None:
         raise PicoException('CSRF token not included in request', 403)
     if session['token'] != submitted_token:
         raise PicoException('CSRF token is not correct', 403)
     return f(*args, **kwds)
예제 #16
0
파일: user.py 프로젝트: syclops/ctflab
 def wrapper(*args, **kwds):
     if "token" not in session:
         raise PicoException(
             "Internal server error",
             data={"debug": "CSRF token not found in session"},
         )
     submitted_token = request.headers.get("X-CSRF-Token", None)
     if submitted_token is None:
         raise PicoException("CSRF token not included in request", 403)
     if session["token"] != submitted_token:
         raise PicoException("CSRF token is not correct", 403)
     return f(*args, **kwds)
예제 #17
0
 def get(self, scoreboard_id):
     """Get a list of teams' score progressions."""
     req = score_progressions_req.parse_args(strict=True)
     scoreboard = api.scoreboards.get_scoreboard(scoreboard_id)
     if not scoreboard:
         raise PicoException('Scoreboard not found', 404)
     if req['limit'] and (not api.user.is_logged_in()
                          or not api.user.get_user()['admin']):
         raise PicoException('Must be admin to specify limit', 403)
     return jsonify(
         api.stats.get_top_teams_score_progressions(
             limit=(req['limit'] or 5), scoreboard_id=scoreboard_id))
예제 #18
0
 def get(self, problem_id):
     """Get the walkthrough for a problem, if unlocked."""
     uid = api.user.get_user()['uid']
     problem = api.problem.get_problem(problem_id)
     if problem is None:
         raise PicoException('Problem not found', 404)
     if problem.get('walkthrough', None) is None:
         raise PicoException('This problem does not have a walkthrough!',
                             status_code=404)
     if problem['pid'] not in api.problem.get_unlocked_walkthroughs(uid):
         raise PicoException("You haven't unlocked this walkthrough yet!",
                             status_code=403)
     return jsonify({'walkthrough': problem['walkthrough']})
예제 #19
0
    def delete(self, group_id):
        """Delete a group. Must be the owner of the group."""
        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException('Group not found', 404)

        curr_user = api.user.get_user()
        if (curr_user['tid'] != group['owner'] and not curr_user['admin']):
            raise PicoException(
                'You do not have permission to delete this group.', 403)

        api.group.delete_group(group_id)
        return jsonify({'success': True})
예제 #20
0
def get_assigned_server_number(new_team=True, tid=None):
    """
    Assign a server number based on current team count and configured stepping.

    Returns:
         (int) server_number

    """
    settings = api.config.get_settings()["shell_servers"]
    db = api.db.get_conn()

    if new_team:
        team_count = db.teams.count()
    else:
        if not tid:
            raise PicoException("tid must be specified.")
        oid = db.teams.find_one({"tid": tid}, {"_id": 1})
        if not oid:
            raise PicoException("Invalid tid.")
        team_count = db.teams.count({"_id": {"$lt": oid["_id"]}})

    assigned_number = 1

    steps = settings["steps"]

    if steps:
        if team_count < steps[-1]:
            for i, step in enumerate(steps):
                if team_count < step:
                    assigned_number = i + 1
                    break
        else:
            assigned_number = (
                1
                + len(steps)
                + (team_count - steps[-1]) // settings["default_stepping"]
            )

    else:
        assigned_number = team_count // settings["default_stepping"] + 1

    if settings["limit_added_range"]:
        max_number = list(
            db.shell_servers.find({}, {"server_number": 1})
            .sort("server_number", -1)
            .limit(1)
        )[0]["server_number"]
        return min(max_number, assigned_number)
    else:
        return assigned_number
예제 #21
0
파일: groups.py 프로젝트: syclops/ctflab
    def get(self, group_id):
        """Remove your own team from this group."""
        group = api.group.get_group(group_id)
        if not group:
            raise PicoException("Classroom not found", 404)
        eligible_for_removal = group["members"] + group["teachers"]
        curr_tid = api.user.get_user()["tid"]

        if curr_tid not in eligible_for_removal:
            raise PicoException(
                "Team is not eligible for removal from this classroom",
                status_code=422)
        api.group.leave_group(group_id, curr_tid)
        return jsonify({"success": True})
예제 #22
0
    def get(self, group_id):
        """Get flag sharing statistics for a specific group."""
        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException('Group not found', 404)

        curr_user = api.user.get_user()
        if (curr_user['tid'] not in (group['teachers'] + [group['owner']])
                and not curr_user['admin']):
            raise PicoException(
                'You do not have permission to view these statistics.', 403)

        return jsonify(
            api.stats.check_invalid_instance_submissions(group['gid']))
예제 #23
0
    def get(self, group_id):
        """Remove your own team from this group."""
        group = api.group.get_group(group_id)
        if not group:
            raise PicoException('Group not found', 404)
        eligible_for_removal = group['members'] + group['teachers']
        curr_tid = api.user.get_user()['tid']

        if curr_tid not in eligible_for_removal:
            raise PicoException(
                'Specified team is not eligible for removal from this group',
                status_code=422)
        api.group.leave_group(group_id, curr_tid)
        return jsonify({'success': True})
예제 #24
0
    def post(self):
        """Join a team by providing its name and password."""
        current_user = api.user.get_user()
        if current_user['teacher']:
            raise PicoException('Teachers may not join teams!', 403)
        req = team_change_req.parse_args(strict=True)

        # Ensure that the team exists
        team = api.team.get_team(name=req['team_name'])
        if team is None:
            raise PicoException('Team not found', 404)
        api.team.join_team(req['team_name'], req['team_password'],
                           current_user)
        return jsonify({'success': True})
예제 #25
0
파일: problem.py 프로젝트: syclops/ctflab
def assign_instance_to_team(pid, tid=None, reassign=False):
    """
    Assign an instance of problem pid to team tid.

    Args:
        pid: the problem id
        tid: the team id
        reassign: whether or not we should assign over an old assignment

    Returns:
        The iid that was assigned

    """
    team = api.team.get_team(tid=tid)
    problem = get_problem(pid)

    available_instances = problem["instances"]

    settings = api.config.get_settings()
    if settings["shell_servers"]["enable_sharding"]:
        available_instances = list(
            filter(
                lambda i: i.get("server_number") == team.get(
                    "server_number", 1),
                problem["instances"],
            ))

    if pid in team["instances"] and not reassign:
        raise PicoException(
            "Team with tid {} already has an instance of pid {}.".format(
                tid, pid))

    if len(available_instances) == 0:
        if settings["shell_servers"]["enable_sharding"]:
            raise PicoException(
                "Your assigned shell server is currently down. " +
                "Please contact an admin.")
        else:
            raise PicoException(
                "Problem {} has no instances to assign.".format(pid))

    instance_number = randint(0, len(available_instances) - 1)
    iid = available_instances[instance_number]["iid"]

    team["instances"][pid] = iid

    db = api.db.get_conn()
    db.teams.update({"tid": tid}, {"$set": team})

    return instance_number
예제 #26
0
파일: email.py 프로젝트: materaj2/picoCTF
def request_password_reset(username):
    """
    Email a user a link to reset their password.

    Args:
        username: the username of the account

    Raises:
        PicoException: if provided username not found

    """
    refresh_email_settings()
    user = api.user.get_user(name=username)
    if user is None:
        raise PicoException('Username not found', 404)

    token_value = api.token.set_token({"uid": user['uid']}, "password_reset")

    settings = api.config.get_settings()

    body = settings["email"]["reset_password_body"].format(  # noqa:E501
        competition_name=settings["competition_name"],
        competition_url=settings["competition_url"],
        username=username,
        token_value=token_value)

    subject = "{} Password Reset".format(settings["competition_name"])

    message = Message(body=body, recipients=[user['email']], subject=subject)
    mail.send(message)
예제 #27
0
    def post(self, group_id):
        """Send an email invite to join this team."""
        req = group_invite_req.parse_args(strict=True)
        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException('Group not found', 404)

        curr_user = api.user.get_user()
        if (curr_user['tid'] not in (group['teachers'] + [group['owner']])
                and not curr_user['admin']):
            raise PicoException(
                'You do not have permission to invite members to this group.',
                status_code=403)

        api.email.send_email_invite(group_id, req['email'], req['as_teacher'])
        return jsonify({'success': True})
예제 #28
0
    def patch(self, group_id):
        """Modify a group's settings (other fields are not available)."""
        req = group_patch_req.parse_args(strict=True)

        group = api.group.get_group(gid=group_id)
        if not group:
            raise PicoException('Group not found', 404)

        curr_user = api.user.get_user()
        if (curr_user['tid'] not in ([group['owner']] + group['teachers'])
                and not curr_user['admin']):
            raise PicoException(
                'You do not have permission to modify this group.', 403)

        api.group.change_group_settings(group_id, req['settings'])
        return jsonify({'success': True})
예제 #29
0
 def get(self, problem_id):
     """Get the walkthrough for a problem, if unlocked."""
     uid = api.user.get_user()["uid"]
     problem = api.problem.get_problem(problem_id, {
         "pid": 1,
         "walkthrough": 1
     })
     if problem is None:
         raise PicoException("Problem not found", 404)
     if problem.get("walkthrough", None) is None:
         raise PicoException("This problem does not have a walkthrough!",
                             status_code=404)
     if problem["pid"] not in api.problem.get_unlocked_walkthroughs(uid):
         raise PicoException("You haven't unlocked this walkthrough yet!",
                             status_code=403)
     return jsonify({"walkthrough": problem["walkthrough"]})
예제 #30
0
    def get(self, team_id):
        """
        Re-evaluate a team's scoreboard eligibilities.

        May be useful if a former member who had previously caused their
        team to become ineligible for a scoreboard deletes their account,
        or if a new scoreboard is added after the team's creation.
        """
        team = api.team.get_team(team_id)
        if not team:
            raise PicoException('Team not found', 404)

        team_members = api.team.get_team_members(tid=team_id,
                                                 show_disabled=False)
        all_scoreboards = api.scoreboards.get_all_scoreboards()
        member_eligibilities = dict()
        for member in team_members:
            member_eligibilities[member['uid']] = {
                scoreboard['sid']
                for scoreboard in all_scoreboards
                if api.scoreboards.is_eligible(member, scoreboard)
            }

        team_eligibilities = list(
            set.intersection(*member_eligibilities.values()))
        db = api.db.get_conn()
        db.teams.find_one_and_update(
            {"tid": team_id}, {"$set": {
                "eligibilities": team_eligibilities
            }})

        return jsonify({'success': True, 'eligibilities': team_eligibilities})