예제 #1
0
파일: teams.py 프로젝트: yoooov/CTFd
    def patch(self):
        team = get_current_team()
        if team.captain_id != session["id"]:
            return (
                {
                    "success": False,
                    "errors": {
                        "": ["Only team captains can edit team information"]
                    },
                },
                403,
            )

        data = request.get_json()

        response = TeamSchema(view="self", instance=team,
                              partial=True).load(data)

        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.commit()
        clear_team_session(team_id=team.id)
        response = TeamSchema("self").dump(response.data)
        db.session.close()

        return {"success": True, "data": response.data}
예제 #2
0
    def delete(self):
        team_disbanding = get_config("team_disbanding", default="inactive_only")
        if team_disbanding == "disabled":
            return (
                {
                    "success": False,
                    "errors": {"": ["Team disbanding is currently disabled"]},
                },
                403,
            )

        team = get_current_team()
        if team.captain_id != session["id"]:
            return (
                {
                    "success": False,
                    "errors": {"": ["Only team captains can disband their team"]},
                },
                403,
            )

        # The team must not have performed any actions in the CTF
        performed_actions = any(
            [
                team.solves != [],
                team.fails != [],
                team.awards != [],
                Submissions.query.filter_by(team_id=team.id).all() != [],
                Unlocks.query.filter_by(team_id=team.id).all() != [],
            ]
        )

        if performed_actions:
            return (
                {
                    "success": False,
                    "errors": {
                        "": [
                            "You cannot disband your team as it has participated in the event. "
                            "Please contact an admin to disband your team or remove a member."
                        ]
                    },
                },
                403,
            )

        for member in team.members:
            member.team_id = None
            clear_user_session(user_id=member.id)

        db.session.delete(team)
        db.session.commit()

        clear_team_session(team_id=team.id)
        clear_standings()

        db.session.close()

        return {"success": True}
예제 #3
0
def join():
    infos = get_infos()
    errors = get_errors()

    user = get_current_user_attrs()
    if user.team_id:
        errors.append("You are already in a team. You cannot join another.")

    if request.method == "GET":
        team_size_limit = get_config("team_size", default=0)
        if team_size_limit:
            plural = "" if team_size_limit == 1 else "s"
            infos.append("Teams are limited to {limit} member{plural}".format(
                limit=team_size_limit, plural=plural))
        return render_template("teams/join_team.html",
                               infos=infos,
                               errors=errors)

    if request.method == "POST":
        teamname = request.form.get("name")
        passphrase = request.form.get("password", "").strip()

        team = Teams.query.filter_by(name=teamname).first()

        if errors:
            return (
                render_template("teams/join_team.html",
                                infos=infos,
                                errors=errors),
                403,
            )

        if team and verify_password(passphrase, team.password):
            team_size_limit = get_config("team_size", default=0)
            if team_size_limit and len(team.members) >= team_size_limit:
                errors.append(
                    "{name} has already reached the team size limit of {limit}"
                    .format(name=team.name, limit=team_size_limit))
                return render_template("teams/join_team.html",
                                       infos=infos,
                                       errors=errors)

            user = get_current_user()
            user.team_id = team.id
            db.session.commit()

            if len(team.members) == 1:
                team.captain_id = user.id
                db.session.commit()

            clear_user_session(user_id=user.id)
            clear_team_session(team_id=team.id)

            return redirect(url_for("challenges.listing"))
        else:
            errors.append("That information is incorrect")
            return render_template("teams/join_team.html",
                                   infos=infos,
                                   errors=errors)
예제 #4
0
파일: teams.py 프로젝트: itsTurnip/CTFd
def join():
    infos = get_infos()
    errors = get_errors()
    if request.method == "GET":
        team_size_limit = get_config("team_size", default=0)
        if team_size_limit:
            plural = "" if team_size_limit == 1 else "s"
            infos.append(
                "Команды могут содержать не больше {limit} участников".format(
                    limit=team_size_limit, plural=plural))
        return render_template("teams/join_team.html",
                               infos=infos,
                               errors=errors)

    if request.method == "POST":
        teamname = request.form.get("name")
        passphrase = request.form.get("password", "").strip()

        team = Teams.query.filter_by(name=teamname).first()

        if team and verify_password(passphrase, team.password):
            team_size_limit = get_config("team_size", default=0)
            if team_size_limit and len(team.members) >= team_size_limit:
                errors.append(
                    "Команда {name} уже достигла лимит в {limit} участников".
                    format(name=team.name, limit=team_size_limit))
                return render_template("teams/join_team.html",
                                       infos=infos,
                                       errors=errors)

            user = get_current_user()
            user.team_id = team.id
            db.session.commit()

            if len(team.members) == 1:
                team.captain_id = user.id
                db.session.commit()

            clear_user_session(user_id=user.id)
            clear_team_session(team_id=team.id)

            return redirect(url_for("challenges.listing"))
        else:
            errors.append("Такая информация некорректна")
            return render_template("teams/join_team.html",
                                   infos=infos,
                                   errors=errors)
예제 #5
0
    def delete(self, team_id):
        team = Teams.query.filter_by(id=team_id).first_or_404()
        team_id = team.id

        for member in team.members:
            member.team_id = None
            clear_user_session(user_id=member.id)

        db.session.delete(team)
        db.session.commit()

        clear_team_session(team_id=team_id)
        clear_standings()

        db.session.close()

        return {"success": True}
예제 #6
0
파일: teams.py 프로젝트: AIica/Crypto-2020
def new():
    infos = get_infos()
    errors = get_errors()
    if request.method == "GET":
        team_size_limit = get_config("team_size", default=0)
        if team_size_limit:
            plural = "" if team_size_limit == 1 else "s"
            infos.append(
                "Teams are limited to {limit} member{plural}".format(
                    limit=team_size_limit, plural=plural
                )
            )

        return render_template("teams/new_team.html", infos=infos, errors=errors)
    elif request.method == "POST":
        teamname = request.form.get("name", "").strip()
        passphrase = request.form.get("password", "").strip()
        errors = get_errors()

        user = get_current_user()

        existing_team = Teams.query.filter_by(name=teamname).first()
        if existing_team:
            errors.append("That team name is already taken")
        if not teamname:
            errors.append("That team name is invalid")

        if errors:
            return render_template("teams/new_team.html", errors=errors)

        team = Teams(name=teamname, password=passphrase, captain_id=user.id)

        db.session.add(team)
        db.session.commit()

        user.team_id = team.id
        db.session.commit()

        clear_user_session(user_id=user.id)
        clear_team_session(team_id=team.id)

        return redirect(url_for("challenges.listing"))
예제 #7
0
    def patch(self, team_id):
        team = Teams.query.filter_by(id=team_id).first_or_404()
        data = request.get_json()
        data["id"] = team_id

        schema = TeamSchema(view="admin", instance=team, partial=True)

        response = schema.load(data)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        response = schema.dump(response.data)
        db.session.commit()

        clear_team_session(team_id=team.id)
        clear_standings()

        db.session.close()

        return {"success": True, "data": response.data}
예제 #8
0
def invite():
    infos = get_infos()
    errors = get_errors()
    code = request.args.get("code")

    if code is None:
        abort(404)

    user = get_current_user_attrs()
    if user.team_id:
        errors.append("You are already in a team. You cannot join another.")

    try:
        team = Teams.load_invite_code(code)
    except TeamTokenExpiredException:
        abort(403, description="This invite URL has expired")
    except TeamTokenInvalidException:
        abort(403, description="This invite URL is invalid")

    team_size_limit = get_config("team_size", default=0)

    if request.method == "GET":
        if team_size_limit:
            infos.append(
                "Teams are limited to {limit} member{plural}".format(
                    limit=team_size_limit, plural=pluralize(number=team_size_limit)
                )
            )

        return render_template(
            "teams/invite.html", team=team, infos=infos, errors=errors
        )

    if request.method == "POST":
        if errors:
            return (
                render_template(
                    "teams/invite.html", team=team, infos=infos, errors=errors
                ),
                403,
            )

        if team_size_limit and len(team.members) >= team_size_limit:
            errors.append(
                "{name} has already reached the team size limit of {limit}".format(
                    name=team.name, limit=team_size_limit
                )
            )
            return (
                render_template(
                    "teams/invite.html", team=team, infos=infos, errors=errors
                ),
                403,
            )

        user = get_current_user()
        user.team_id = team.id
        db.session.commit()

        clear_user_session(user_id=user.id)
        clear_team_session(team_id=team.id)

        return redirect(url_for("challenges.listing"))
예제 #9
0
def new():
    infos = get_infos()
    errors = get_errors()

    if bool(get_config("team_creation", default=True)) is False:
        abort(
            403,
            description="Team creation is currently disabled. Please join an existing team.",
        )

    num_teams_limit = int(get_config("num_teams", default=0))
    num_teams = Teams.query.filter_by(banned=False, hidden=False).count()
    if num_teams_limit and num_teams >= num_teams_limit:
        abort(
            403,
            description=f"Reached the maximum number of teams ({num_teams_limit}). Please join an existing team.",
        )

    user = get_current_user_attrs()
    if user.team_id:
        errors.append("You are already in a team. You cannot join another.")

    if request.method == "GET":
        team_size_limit = get_config("team_size", default=0)
        if team_size_limit:
            plural = "" if team_size_limit == 1 else "s"
            infos.append(
                "Teams are limited to {limit} member{plural}".format(
                    limit=team_size_limit, plural=plural
                )
            )
        return render_template("teams/new_team.html", infos=infos, errors=errors)

    elif request.method == "POST":
        teamname = request.form.get("name", "").strip()
        passphrase = request.form.get("password", "").strip()

        website = request.form.get("website")
        affiliation = request.form.get("affiliation")

        user = get_current_user()

        existing_team = Teams.query.filter_by(name=teamname).first()
        if existing_team:
            errors.append("That team name is already taken")
        if not teamname:
            errors.append("That team name is invalid")

        # Process additional user fields
        fields = {}
        for field in TeamFields.query.all():
            fields[field.id] = field

        entries = {}
        for field_id, field in fields.items():
            value = request.form.get(f"fields[{field_id}]", "").strip()
            if field.required is True and (value is None or value == ""):
                errors.append("Please provide all required fields")
                break

            # Handle special casing of existing profile fields
            if field.name.lower() == "affiliation":
                affiliation = value
                break
            elif field.name.lower() == "website":
                website = value
                break

            if field.field_type == "boolean":
                entries[field_id] = bool(value)
            else:
                entries[field_id] = value

        if website:
            valid_website = validators.validate_url(website)
        else:
            valid_website = True

        if affiliation:
            valid_affiliation = len(affiliation) < 128
        else:
            valid_affiliation = True

        if valid_website is False:
            errors.append("Websites must be a proper URL starting with http or https")
        if valid_affiliation is False:
            errors.append("Please provide a shorter affiliation")

        if errors:
            return render_template("teams/new_team.html", errors=errors), 403

        team = Teams(name=teamname, password=passphrase, captain_id=user.id)

        if website:
            team.website = website
        if affiliation:
            team.affiliation = affiliation

        db.session.add(team)
        db.session.commit()

        for field_id, value in entries.items():
            entry = TeamFieldEntries(field_id=field_id, value=value, team_id=team.id)
            db.session.add(entry)
        db.session.commit()

        user.team_id = team.id
        db.session.commit()

        clear_user_session(user_id=user.id)
        clear_team_session(team_id=team.id)

        return redirect(url_for("challenges.listing"))
예제 #10
0
def oauth_redirect():
    oauth_code = request.args.get("code")
    state = request.args.get("state")
    if session["nonce"] != state:
        log("logins", "[{date}] {ip} - OAuth State validation mismatch")
        error_for(endpoint="auth.login",
                  message="OAuth State validation mismatch.")
        return redirect(url_for("auth.login"))

    if oauth_code:
        url = (get_app_config("OAUTH_TOKEN_ENDPOINT")
               or get_config("oauth_token_endpoint")
               or "https://auth.majorleaguecyber.org/oauth/token")

        client_id = get_app_config("OAUTH_CLIENT_ID") or get_config(
            "oauth_client_id")
        client_secret = get_app_config("OAUTH_CLIENT_SECRET") or get_config(
            "oauth_client_secret")
        headers = {"content-type": "application/x-www-form-urlencoded"}
        data = {
            "code": oauth_code,
            "client_id": client_id,
            "client_secret": client_secret,
            "grant_type": "authorization_code",
        }
        token_request = requests.post(url, data=data, headers=headers)

        if token_request.status_code == requests.codes.ok:
            token = token_request.json()["access_token"]
            user_url = (get_app_config("OAUTH_API_ENDPOINT")
                        or get_config("oauth_api_endpoint")
                        or "https://api.majorleaguecyber.org/user")

            headers = {
                "Authorization": "Bearer " + str(token),
                "Content-type": "application/json",
            }
            api_data = requests.get(url=user_url, headers=headers).json()

            user_id = api_data["id"]
            user_name = api_data["name"]
            user_email = api_data["email"]

            user = Users.query.filter_by(email=user_email).first()
            if user is None:
                # Check if we are allowing registration before creating users
                if registration_visible() or mlc_registration():
                    user = Users(
                        name=user_name,
                        email=user_email,
                        oauth_id=user_id,
                        verified=True,
                    )
                    db.session.add(user)
                    db.session.commit()
                else:
                    log("logins",
                        "[{date}] {ip} - Public registration via MLC blocked")
                    error_for(
                        endpoint="auth.login",
                        message=
                        "Public registration is disabled. Please try again later.",
                    )
                    return redirect(url_for("auth.login"))

            if get_config("user_mode") == TEAMS_MODE:
                team_id = api_data["team"]["id"]
                team_name = api_data["team"]["name"]

                team = Teams.query.filter_by(oauth_id=team_id).first()
                if team is None:
                    team = Teams(name=team_name,
                                 oauth_id=team_id,
                                 captain_id=user.id)
                    db.session.add(team)
                    db.session.commit()
                    clear_team_session(team_id=team.id)

                team_size_limit = get_config("team_size", default=0)
                if team_size_limit and len(team.members) >= team_size_limit:
                    plural = "" if team_size_limit == 1 else "s"
                    size_error = "Teams are limited to {limit} member{plural}.".format(
                        limit=team_size_limit, plural=plural)
                    error_for(endpoint="auth.login", message=size_error)
                    return redirect(url_for("auth.login"))

                team.members.append(user)
                db.session.commit()

            if user.oauth_id is None:
                user.oauth_id = user_id
                user.verified = True
                db.session.commit()
                clear_user_session(user_id=user.id)

            login_user(user)

            return redirect(url_for("challenges.listing"))
        else:
            log("logins", "[{date}] {ip} - OAuth token retrieval failure")
            error_for(endpoint="auth.login",
                      message="OAuth token retrieval failure.")
            return redirect(url_for("auth.login"))
    else:
        log("logins", "[{date}] {ip} - Received redirect without OAuth code")
        error_for(endpoint="auth.login",
                  message="Received redirect without OAuth code.")
        return redirect(url_for("auth.login"))
예제 #11
0
파일: teams.py 프로젝트: itsTurnip/CTFd
def new():
    infos = get_infos()
    errors = get_errors()
    if request.method == "GET":
        team_size_limit = get_config("team_size", default=0)
        if team_size_limit:
            plural = "" if team_size_limit == 1 else "s"
            infos.append("Teams are limited to {limit} member{plural}".format(
                limit=team_size_limit, plural=plural))

        return render_template("teams/new_team.html",
                               infos=infos,
                               errors=errors)
    elif request.method == "POST":
        teamname = request.form.get("name", "").strip()
        passphrase = request.form.get("password", "").strip()
        errors = get_errors()

        website = request.form.get("website")
        affiliation = request.form.get("affiliation")

        user = get_current_user()

        existing_team = Teams.query.filter_by(name=teamname).first()
        if existing_team:
            errors.append("Такое имя команды уже занято")
        if not teamname:
            errors.append("Имя команды неправильное")

        # Process additional user fields
        fields = {}
        for field in TeamFields.query.all():
            fields[field.id] = field

        entries = {}
        for field_id, field in fields.items():
            value = request.form.get(f"fields[{field_id}]", "").strip()
            if field.required is True and (value is None or value == ""):
                errors.append("Пожалуйста, укажите все обязательные поля")
                break

            # Handle special casing of existing profile fields
            if field.name.lower() == "affiliation":
                affiliation = value
                break
            elif field.name.lower() == "website":
                website = value
                break

            if field.field_type == "boolean":
                entries[field_id] = bool(value)
            else:
                entries[field_id] = value

        if website:
            valid_website = validators.validate_url(website)
        else:
            valid_website = True

        if affiliation:
            valid_affiliation = len(affiliation) < 128
        else:
            valid_affiliation = True

        if valid_website is False:
            errors.append(
                "Вебсайт должен быть правильной ссылкой, начинающейся с http или https"
            )
        if valid_affiliation is False:
            errors.append("Пожалуйста, укажите учреждение покороче")

        if errors:
            return render_template("teams/new_team.html", errors=errors)

        team = Teams(name=teamname, password=passphrase, captain_id=user.id)

        if website:
            team.website = website
        if affiliation:
            team.affiliation = affiliation

        db.session.add(team)
        db.session.commit()

        for field_id, value in entries.items():
            entry = TeamFieldEntries(field_id=field_id,
                                     value=value,
                                     team_id=team.id)
            db.session.add(entry)
        db.session.commit()

        user.team_id = team.id
        db.session.commit()

        clear_user_session(user_id=user.id)
        clear_team_session(team_id=team.id)

        return redirect(url_for("challenges.listing"))