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"))
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"))
def test_api_team_self_fields_permissions(): app = create_ctfd(user_mode="teams") with app.app_context(): register_user(app) team = gen_team(app.db) user = Users.query.filter_by(id=2).first() user.team_id = team.id app.db.session.commit() team = Teams.query.filter_by(id=1).first() team.captain_id = 2 app.db.session.commit() gen_field( app.db, name="CustomField1", type="team", public=False, editable=False ) gen_field(app.db, name="CustomField2", type="team", public=True, editable=True) app.db.session.add( TeamFieldEntries(type="team", value="CustomValue1", team_id=1, field_id=1) ) app.db.session.add( TeamFieldEntries(type="team", value="CustomValue2", team_id=1, field_id=2) ) app.db.session.commit() assert len(team.field_entries) == 2 with login_as_user(app) as user, login_as_user(app, name="admin") as admin: r = user.get("/api/v1/teams/me") resp = r.get_json() assert resp["data"]["fields"] == [ { "value": "CustomValue2", "name": "CustomField2", "description": "CustomFieldDescription", "type": "text", "field_id": 2, } ] assert len(resp["data"]["fields"]) == 1 # Admin gets data and should see all fields r = admin.get("/api/v1/teams/1") resp = r.get_json() assert len(resp["data"]["fields"]) == 2 r = user.patch( "/api/v1/teams/me", json={ "fields": [ {"field_id": 1, "value": "NewCustomValue1"}, {"field_id": 2, "value": "NewCustomValue2"}, ] }, ) assert r.get_json() == { "success": False, "errors": {"fields": ["Field 'CustomField1' cannot be editted"]}, } assert r.status_code == 400 assert ( TeamFieldEntries.query.filter_by(id=1).first().value == "CustomValue1" ) assert ( TeamFieldEntries.query.filter_by(id=2).first().value == "CustomValue2" ) # After making the field public the user should see both fields field = Fields.query.filter_by(id=1).first() field.public = True app.db.session.commit() r = user.get("/api/v1/teams/me") resp = r.get_json() assert len(resp["data"]["fields"]) == 2 # Captain should be able to edit their values after it's made editable field = Fields.query.filter_by(id=1).first() field.editable = True app.db.session.commit() r = user.patch( "/api/v1/teams/me", json={ "fields": [ {"field_id": 1, "value": "NewCustomValue1"}, {"field_id": 2, "value": "NewCustomValue2"}, ] }, ) print(r.get_json()) assert r.status_code == 200 assert ( TeamFieldEntries.query.filter_by(id=1).first().value == "NewCustomValue1" ) assert ( TeamFieldEntries.query.filter_by(id=2).first().value == "NewCustomValue2" ) destroy_ctfd(app)