init CTFd source
This commit is contained in:
0
tests/teams/__init__.py
Normal file
0
tests/teams/__init__.py
Normal file
245
tests/teams/test_auth.py
Normal file
245
tests/teams/test_auth.py
Normal file
@@ -0,0 +1,245 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.models import Teams, Users, db
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
register_user,
|
||||
)
|
||||
|
||||
|
||||
def test_banned_team():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
team = gen_team(app.db, banned=True)
|
||||
user = Users.query.filter_by(id=2).first()
|
||||
user.team_id = team.id
|
||||
db.session.commit()
|
||||
|
||||
client = login_as_user(app)
|
||||
|
||||
routes = ["/", "/challenges", "/api/v1/challenges"]
|
||||
for route in routes:
|
||||
r = client.get(route)
|
||||
assert r.status_code == 403
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_join_get():
|
||||
"""Can a user get /teams/join"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_join_post():
|
||||
"""Can a user post /teams/join"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
gen_team(app.db, name="team")
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/join", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
# Cannot join a team with an incorrect password
|
||||
incorrect_data = data
|
||||
incorrect_data["password"] = ""
|
||||
r = client.post("/teams/join", data=incorrect_data)
|
||||
assert r.status_code == 403
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_join_when_already_on_team():
|
||||
"""Test that a user cannot join another team"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
gen_team(app.db, email="team1@examplectf.com", name="team1")
|
||||
gen_team(app.db, email="team2@examplectf.com", name="team2")
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team1",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/join", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
# Try to join another team while on a team
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team2",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/join", data=data)
|
||||
assert r.status_code == 403
|
||||
user = Users.query.filter_by(name="user").first()
|
||||
assert user.team.name == "team1"
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_login():
|
||||
"""Can a user login as a team"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db, name="user")
|
||||
team = gen_team(app.db)
|
||||
user.team_id = team.id
|
||||
team.members.append(user)
|
||||
app.db.session.commit()
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/team")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_join_ratelimited():
|
||||
"""Test that team joins are ratelimited"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
gen_team(app.db, name="team")
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "wrong_password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
for _ in range(10):
|
||||
r = client.post("/teams/join", data=data)
|
||||
|
||||
data["password"] = "password"
|
||||
for _ in range(10):
|
||||
r = client.post("/teams/join", data=data)
|
||||
assert r.status_code == 429
|
||||
assert Users.query.filter_by(id=2).first().team_id is None
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_new_get():
|
||||
"""Can a user get /teams/new"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_new_post():
|
||||
"""Can a user post /teams/new"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
with login_as_user(app) as client:
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
# You can't create a team with a duplicate name
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 403
|
||||
|
||||
# You can't create a team with an empty name
|
||||
incorrect_data = data
|
||||
incorrect_data["name"] = ""
|
||||
r = client.post("/teams/new", data=incorrect_data)
|
||||
assert r.status_code == 403
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_new_post_when_already_on_team():
|
||||
"""Test that a user cannot create a new team while on a team"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
with login_as_user(app) as client:
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team1",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
# Try to create another team while on a team
|
||||
r = client.get("/teams/new")
|
||||
assert r.status_code == 200
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team2",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/join", data=data)
|
||||
assert r.status_code == 403
|
||||
user = Users.query.filter_by(name="user").first()
|
||||
assert user.team.name == "team1"
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_from_admin_hidden():
|
||||
"""Test that teams created by admins in /teams/new are hidden by default"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_user(app.db, name="user")
|
||||
with login_as_user(app) as client:
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team_user",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
team = Teams.query.filter_by(name="team_user").first()
|
||||
assert team.hidden == False
|
||||
|
||||
with login_as_user(app, "admin") as client:
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team_admin",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
team = Teams.query.filter_by(name="team_admin").first()
|
||||
assert team.hidden == True
|
||||
destroy_ctfd(app)
|
||||
65
tests/teams/test_challenges.py
Normal file
65
tests/teams/test_challenges.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.utils import set_config
|
||||
from CTFd.utils.scores import get_standings
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_challenge,
|
||||
gen_flag,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
register_user,
|
||||
)
|
||||
|
||||
|
||||
def test_challenge_team_submit():
|
||||
"""Is a user's solved challenge reflected by other team members"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db)
|
||||
second_user = gen_user(app.db, name="user", email="second@examplectf.com")
|
||||
team = gen_team(app.db)
|
||||
user.team_id = team.id
|
||||
second_user.team_id = team.id
|
||||
team.members.append(user)
|
||||
team.members.append(second_user)
|
||||
gen_challenge(app.db)
|
||||
gen_flag(app.db, 1)
|
||||
app.db.session.commit()
|
||||
with login_as_user(app, name="user_name") as client:
|
||||
flag = {"challenge_id": 1, "submission": "flag"}
|
||||
client.post("/api/v1/challenges/attempt", json=flag)
|
||||
with login_as_user(app) as second_client:
|
||||
flag = {"challenge_id": 1, "submission": "flag"}
|
||||
r = second_client.post("/api/v1/challenges/attempt", json=flag)
|
||||
assert r.json["data"]["status"] == "already_solved"
|
||||
standings = get_standings()
|
||||
assert standings[0].name == "team_name"
|
||||
assert standings[0].score == 100
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_anonymous_users_view_public_challenges_without_team():
|
||||
"""Test that if challenges are public, users without team can still view them"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
gen_challenge(app.db)
|
||||
with app.test_client() as client:
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 302
|
||||
assert r.location.startswith("/login")
|
||||
|
||||
set_config("challenge_visibility", "public")
|
||||
with app.test_client() as client:
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 200
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 302
|
||||
assert r.location.startswith("/team")
|
||||
destroy_ctfd(app)
|
||||
396
tests/teams/test_fields.py
Normal file
396
tests/teams/test_fields.py
Normal file
@@ -0,0 +1,396 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.models import TeamFieldEntries, Teams, Users
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_field,
|
||||
gen_team,
|
||||
login_as_user,
|
||||
register_user,
|
||||
)
|
||||
|
||||
|
||||
def test_new_fields_show_on_pages():
|
||||
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
|
||||
team = Teams.query.filter_by(id=1).first()
|
||||
team.captain_id = 2
|
||||
app.db.session.commit()
|
||||
|
||||
gen_field(app.db, name="CustomField1", type="team")
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
assert "CustomField1" in r.get_data(as_text=True)
|
||||
assert "CustomFieldDescription" in r.get_data(as_text=True)
|
||||
|
||||
r = client.get("/team")
|
||||
assert "CustomField1" in r.get_data(as_text=True)
|
||||
assert "CustomFieldDescription" in r.get_data(as_text=True)
|
||||
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={"fields": [{"field_id": 1, "value": "CustomFieldEntry"}]},
|
||||
)
|
||||
resp = r.get_json()
|
||||
assert resp["success"] is True
|
||||
assert resp["data"]["fields"][0]["value"] == "CustomFieldEntry"
|
||||
assert resp["data"]["fields"][0]["description"] == "CustomFieldDescription"
|
||||
assert resp["data"]["fields"][0]["name"] == "CustomField1"
|
||||
assert resp["data"]["fields"][0]["field_id"] == 1
|
||||
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomFieldEntry" in resp
|
||||
|
||||
r = client.get("/teams/1")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomFieldEntry" in resp
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_fields_required_on_creation():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
gen_field(app.db, type="team")
|
||||
|
||||
with app.app_context():
|
||||
with login_as_user(app) as client:
|
||||
assert Teams.query.count() == 0
|
||||
r = client.get("/teams/new")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField" in resp
|
||||
assert "CustomFieldDescription" in resp
|
||||
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert "Please provide all required fields" in r.get_data(as_text=True)
|
||||
assert Teams.query.count() == 0
|
||||
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"fields[1]": "CustomFieldEntry",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
assert Teams.query.count() == 1
|
||||
|
||||
entry = TeamFieldEntries.query.filter_by(id=1).first()
|
||||
assert entry.team_id == 1
|
||||
assert entry.value == "CustomFieldEntry"
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_fields_properties():
|
||||
"""Test that custom fields for team can be set and editted"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField1",
|
||||
type="team",
|
||||
required=True,
|
||||
public=True,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField2",
|
||||
type="team",
|
||||
required=False,
|
||||
public=True,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField3",
|
||||
type="team",
|
||||
required=False,
|
||||
public=False,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField4",
|
||||
type="team",
|
||||
required=False,
|
||||
public=False,
|
||||
editable=False,
|
||||
)
|
||||
|
||||
register_user(app)
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" in resp
|
||||
assert "CustomField4" in resp
|
||||
|
||||
# Manually create team so that we can set the required profile field
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"fields[1]": "custom_field_value",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 302
|
||||
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" in resp
|
||||
assert "CustomField4" not in resp
|
||||
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={
|
||||
"fields": [
|
||||
{"field_id": 1, "value": "CustomFieldEntry1"},
|
||||
{"field_id": 2, "value": "CustomFieldEntry2"},
|
||||
{"field_id": 3, "value": "CustomFieldEntry3"},
|
||||
{"field_id": 4, "value": "CustomFieldEntry4"},
|
||||
]
|
||||
},
|
||||
)
|
||||
resp = r.get_json()
|
||||
assert resp == {
|
||||
"success": False,
|
||||
"errors": {"fields": ["Field 'CustomField4' cannot be editted"]},
|
||||
}
|
||||
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={
|
||||
"fields": [
|
||||
{"field_id": 1, "value": "CustomFieldEntry1"},
|
||||
{"field_id": 2, "value": "CustomFieldEntry2"},
|
||||
{"field_id": 3, "value": "CustomFieldEntry3"},
|
||||
]
|
||||
},
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert (
|
||||
"CustomField3" in resp
|
||||
) # This is here because /team contains team settings
|
||||
assert "CustomField4" not in resp
|
||||
|
||||
r = client.get("/teams/1")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" not in resp
|
||||
assert "CustomField4" not in resp
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_boolean_checkbox_field():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField1",
|
||||
type="team",
|
||||
field_type="boolean",
|
||||
required=False,
|
||||
)
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
resp = r.get_data(as_text=True)
|
||||
|
||||
# We should have rendered a checkbox input
|
||||
assert "checkbox" in resp
|
||||
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
"fields[1]": "y",
|
||||
}
|
||||
client.post("/teams/new", data=data)
|
||||
assert Teams.query.count() == 1
|
||||
|
||||
assert TeamFieldEntries.query.count() == 1
|
||||
assert TeamFieldEntries.query.filter_by(id=1).first().value is True
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "checkbox" in resp
|
||||
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me", json={"fields": [{"field_id": 1, "value": False}]}
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert TeamFieldEntries.query.count() == 1
|
||||
assert TeamFieldEntries.query.filter_by(id=1).first().value is False
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_needs_all_required_fields():
|
||||
"""Test that teams need to complete profiles before seeing challenges"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
# Create a user and team who haven't filled any of their fields
|
||||
register_user(app)
|
||||
team = gen_team(app.db)
|
||||
user = Users.query.filter_by(id=2).first()
|
||||
user.team_id = team.id
|
||||
team = Teams.query.filter_by(id=1).first()
|
||||
team.captain_id = 2
|
||||
app.db.session.commit()
|
||||
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField1",
|
||||
type="team",
|
||||
required=True,
|
||||
public=True,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField2",
|
||||
type="team",
|
||||
required=False,
|
||||
public=True,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField3",
|
||||
type="team",
|
||||
required=False,
|
||||
public=False,
|
||||
editable=True,
|
||||
)
|
||||
gen_field(
|
||||
app.db,
|
||||
name="CustomField4",
|
||||
type="team",
|
||||
required=False,
|
||||
public=False,
|
||||
editable=False,
|
||||
)
|
||||
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" in resp
|
||||
assert "CustomField4" in resp
|
||||
|
||||
# We can't view challenges because we have an incomplete team profile
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 403
|
||||
|
||||
# When we go to our profile we should see all fields
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" in resp
|
||||
assert "CustomField4" in resp
|
||||
|
||||
# Set all non-required fields
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={
|
||||
"fields": [
|
||||
# {"field_id": 1, "value": "CustomFieldEntry1"},
|
||||
{"field_id": 2, "value": "CustomFieldEntry2"},
|
||||
{"field_id": 3, "value": "CustomFieldEntry3"},
|
||||
{"field_id": 4, "value": "CustomFieldEntry4"},
|
||||
]
|
||||
},
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
# We can't view challenges because we have an incomplete team profile
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 403
|
||||
|
||||
# Set required fields
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={"fields": [{"field_id": 1, "value": "CustomFieldEntry1"}]},
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
# We can view challenges now
|
||||
r = client.get("/challenges")
|
||||
assert r.status_code == 200
|
||||
|
||||
# Attempts to edit a non-edittable field to field after completing profile
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={"fields": [{"field_id": 4, "value": "CustomFieldEntry4"}]},
|
||||
)
|
||||
resp = r.get_json()
|
||||
assert resp == {
|
||||
"success": False,
|
||||
"errors": {"fields": ["Field 'CustomField4' cannot be editted"]},
|
||||
}
|
||||
|
||||
# I can edit edittable fields
|
||||
r = client.patch(
|
||||
"/api/v1/teams/me",
|
||||
json={
|
||||
"fields": [
|
||||
{"field_id": 1, "value": "CustomFieldEntry1"},
|
||||
{"field_id": 2, "value": "CustomFieldEntry2"},
|
||||
{"field_id": 3, "value": "CustomFieldEntry3"},
|
||||
]
|
||||
},
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
# I should see the correct fields in the private team profile
|
||||
r = client.get("/team")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert (
|
||||
"CustomField3" in resp
|
||||
) # This is here because /team contains team settings
|
||||
assert "CustomField4" not in resp
|
||||
|
||||
# I should see the correct fields in the public team profile
|
||||
r = client.get("/teams/1")
|
||||
resp = r.get_data(as_text=True)
|
||||
assert "CustomField1" in resp
|
||||
assert "CustomField2" in resp
|
||||
assert "CustomField3" not in resp
|
||||
assert "CustomField4" not in resp
|
||||
destroy_ctfd(app)
|
||||
91
tests/teams/test_hidden_team_scores.py
Normal file
91
tests/teams/test_hidden_team_scores.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from CTFd.models import Teams
|
||||
from CTFd.utils.scores import get_standings, get_team_standings
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_challenge,
|
||||
gen_flag,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
)
|
||||
|
||||
|
||||
def setup_app(app):
|
||||
user1 = gen_user(app.db, name="user1", email="user1@examplectf.com")
|
||||
team1 = gen_team(app.db, name="team1", email="team1@examplectf.com")
|
||||
user1.team_id = team1.id
|
||||
team1.members.append(user1)
|
||||
team1.hidden = True
|
||||
|
||||
user2 = gen_user(app.db, name="user2", email="user2@examplectf.com")
|
||||
team2 = gen_team(app.db, name="team2", email="team2@examplectf.com")
|
||||
user2.team_id = team2.id
|
||||
team2.members.append(user2)
|
||||
|
||||
gen_challenge(app.db)
|
||||
gen_flag(app.db, 1)
|
||||
|
||||
app.db.session.commit()
|
||||
|
||||
with login_as_user(app, name="user1") as client:
|
||||
flag = {"challenge_id": 1, "submission": "flag"}
|
||||
client.post("/api/v1/challenges/attempt", json=flag)
|
||||
|
||||
with login_as_user(app, name="user2") as client:
|
||||
flag = {"challenge_id": 1, "submission": "flag"}
|
||||
client.post("/api/v1/challenges/attempt", json=flag)
|
||||
|
||||
|
||||
def test_standings():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
|
||||
with app.app_context():
|
||||
setup_app(app)
|
||||
|
||||
standings = get_standings()
|
||||
|
||||
assert standings[0].name == "team2"
|
||||
assert standings[0].score == 100
|
||||
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_standings():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
|
||||
with app.app_context():
|
||||
setup_app(app)
|
||||
|
||||
team_standings = get_team_standings()
|
||||
|
||||
first_team = Teams.query.filter_by(id=team_standings[0].team_id).first_or_404()
|
||||
|
||||
assert first_team.name == "team2"
|
||||
assert first_team.score == 100
|
||||
|
||||
|
||||
def test_admin_standings():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
|
||||
with app.app_context():
|
||||
setup_app(app)
|
||||
|
||||
standings = get_standings(admin=True)
|
||||
|
||||
assert standings[0].name == "team1"
|
||||
assert standings[0].score == 100
|
||||
|
||||
|
||||
def test_admin_team_standings():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
|
||||
with app.app_context():
|
||||
setup_app(app)
|
||||
|
||||
team_standings = get_team_standings(admin=True)
|
||||
|
||||
first_team = Teams.query.filter_by(id=team_standings[0].team_id).first_or_404()
|
||||
|
||||
assert first_team.name == "team1"
|
||||
assert first_team.score == 100
|
||||
138
tests/teams/test_hints.py
Normal file
138
tests/teams/test_hints.py
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.utils.scores import get_standings
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_award,
|
||||
gen_challenge,
|
||||
gen_hint,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
)
|
||||
|
||||
|
||||
def test_hint_team_unlock():
|
||||
"""Is a user's unlocked hint reflected on other team members"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db)
|
||||
second_user = gen_user(app.db, name="user", email="second@examplectf.com")
|
||||
team = gen_team(app.db)
|
||||
user.team_id = team.id
|
||||
second_user.team_id = team.id
|
||||
team.members.append(user)
|
||||
team.members.append(second_user)
|
||||
chal = gen_challenge(app.db)
|
||||
gen_hint(app.db, chal.id, content="hint", cost=1, type="standard")
|
||||
# Give the points to the user that doesn't unlock
|
||||
# Users that unlock hints should be able to unlock but cost their team points
|
||||
gen_award(app.db, user_id=3, team_id=team.id)
|
||||
app.db.session.commit()
|
||||
with login_as_user(app, name="user_name") as client:
|
||||
# Assert that we don't see a hint
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.get_json()["data"].get("content") is None
|
||||
|
||||
# Unlock the hint
|
||||
client.post("/api/v1/unlocks", json={"target": 1, "type": "hints"})
|
||||
|
||||
# Assert that we see a hint
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.get_json()["data"].get("content")
|
||||
with login_as_user(app) as second_client:
|
||||
# Assert that we see a hint
|
||||
r = second_client.get("/api/v1/hints/1")
|
||||
assert r.get_json()["data"].get("content")
|
||||
|
||||
# Assert that we can't double unlock
|
||||
r = second_client.post(
|
||||
"/api/v1/unlocks", json={"target": 1, "type": "hints"}
|
||||
)
|
||||
assert r.status_code == 400
|
||||
assert (
|
||||
r.get_json()["errors"]["target"]
|
||||
== "You've already unlocked this target"
|
||||
)
|
||||
|
||||
# Assert that we see a hint
|
||||
r = second_client.get("/api/v1/hints/1")
|
||||
assert r.json["data"]["content"] == "hint"
|
||||
|
||||
# Verify standings
|
||||
# We start with 100 points from the award.
|
||||
# We lose a point because we unlock successfully once
|
||||
standings = get_standings()
|
||||
assert standings[0].name == "team_name"
|
||||
assert standings[0].score == 99
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_hint_team_unlocking_without_points():
|
||||
"""Test that teams cannot enter negative point valuations from unlocking hints"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db)
|
||||
second_user = gen_user(app.db, name="user", email="second@examplectf.com")
|
||||
team = gen_team(app.db)
|
||||
user.team_id = team.id
|
||||
second_user.team_id = team.id
|
||||
team.members.append(user)
|
||||
team.members.append(second_user)
|
||||
chal = gen_challenge(app.db)
|
||||
gen_hint(app.db, chal.id, content="hint", cost=1, type="standard")
|
||||
app.db.session.commit()
|
||||
with login_as_user(app, name="user_name") as client:
|
||||
# Assert that we don't see a hint
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.get_json()["data"].get("content") is None
|
||||
|
||||
# Attempt to unlock the hint
|
||||
r = client.post("/api/v1/unlocks", json={"target": 1, "type": "hints"})
|
||||
assert r.status_code == 400
|
||||
assert (
|
||||
r.get_json()["errors"]["score"]
|
||||
== "You do not have enough points to unlock this hint"
|
||||
)
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_dont_prevent_other_teams_from_unlocking_hints():
|
||||
"""Unlocks from one user don't affect other users"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
chal = gen_challenge(app.db)
|
||||
gen_hint(app.db, chal.id, content="This is a hint", cost=1, type="standard")
|
||||
|
||||
team1 = gen_team(app.db, name="team1", email="team1@examplectf.com")
|
||||
team2 = gen_team(app.db, name="team2", email="team2@examplectf.com")
|
||||
|
||||
# Give users points with an award
|
||||
gen_award(app.db, user_id=team1.captain_id)
|
||||
gen_award(app.db, user_id=team2.captain_id)
|
||||
|
||||
captain1 = team1.captain.name
|
||||
captain2 = team2.captain.name
|
||||
|
||||
app.db.session.commit()
|
||||
|
||||
# First team unlocks hint
|
||||
with login_as_user(app, name=captain1) as client:
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.status_code == 200
|
||||
r = client.post("/api/v1/unlocks", json={"target": 1, "type": "hints"})
|
||||
assert r.status_code == 200
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.status_code == 200
|
||||
|
||||
# Second team unlocks hint
|
||||
with login_as_user(app, name=captain2) as client:
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.status_code == 200
|
||||
r = client.post("/api/v1/unlocks", json={"target": 1, "type": "hints"})
|
||||
assert r.status_code == 200
|
||||
r = client.get("/api/v1/hints/1")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
81
tests/teams/test_invites.py
Normal file
81
tests/teams/test_invites.py
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from freezegun import freeze_time
|
||||
|
||||
from CTFd.exceptions import TeamTokenExpiredException, TeamTokenInvalidException
|
||||
from CTFd.models import Teams, Users
|
||||
from CTFd.utils import set_config
|
||||
from tests.helpers import create_ctfd, destroy_ctfd, gen_team, gen_user, login_as_user
|
||||
|
||||
|
||||
def test_team_invite_codes():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
team1 = gen_team(app.db, name="team1", email="team1@examplectf.com")
|
||||
with freeze_time("2017-10-7 00:00:00"):
|
||||
invite_code = team1.get_invite_code()
|
||||
team = Teams.load_invite_code(invite_code)
|
||||
assert team.id == team1.id
|
||||
|
||||
with freeze_time("2017-10-8 00:00:01"):
|
||||
try:
|
||||
team = Teams.load_invite_code(invite_code)
|
||||
except TeamTokenExpiredException:
|
||||
# This token should be expired and we shouldn't get a team object back
|
||||
pass
|
||||
else:
|
||||
print("Token should have expired")
|
||||
raise Exception
|
||||
|
||||
# Change team's password
|
||||
team.password = "new_test_password"
|
||||
app.db.session.commit()
|
||||
|
||||
with freeze_time("2017-10-7 00:00:00"):
|
||||
try:
|
||||
team = Teams.load_invite_code(invite_code)
|
||||
except TeamTokenInvalidException:
|
||||
pass
|
||||
else:
|
||||
print("Token should have been invalidated by password change")
|
||||
raise Exception
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_api_user_facing_invite_tokens():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
team1 = gen_team(app.db, name="team1", email="team1@examplectf.com")
|
||||
user = team1.captain
|
||||
with login_as_user(app, name=user.name) as captain:
|
||||
r = captain.post("/api/v1/teams/me/members", json="")
|
||||
invite_code = r.get_json()["data"]["code"]
|
||||
assert invite_code
|
||||
|
||||
new_user = gen_user(app.db)
|
||||
with login_as_user(app, name=new_user.name) as user:
|
||||
url = f"/teams/invite?code={invite_code}"
|
||||
user.get(url)
|
||||
with user.session_transaction() as sess:
|
||||
data = {
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = user.post(url, data=data)
|
||||
assert r.status_code == 302
|
||||
assert r.location.endswith("/challenges")
|
||||
assert Users.query.filter_by(id=new_user.id).first().team_id == team1.id
|
||||
|
||||
# Test team size limits
|
||||
set_config("team_size", 1)
|
||||
new_user2 = gen_user(app.db, name="new_user2", email="new_user2@examplectf.com")
|
||||
with login_as_user(app, name=new_user2.name) as user:
|
||||
url = f"/teams/invite?code={invite_code}"
|
||||
user.get(url)
|
||||
with user.session_transaction() as sess:
|
||||
data = {
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = user.post(url, data=data)
|
||||
assert r.status_code == 403
|
||||
assert "has already reached the team size limit" in r.get_data(as_text=True)
|
||||
destroy_ctfd(app)
|
||||
33
tests/teams/test_scoreboard.py
Normal file
33
tests/teams/test_scoreboard.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.utils.scores import get_standings
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_challenge,
|
||||
gen_flag,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
)
|
||||
|
||||
|
||||
def test_scoreboard_team_score():
|
||||
"""Is a user's submitted flag reflected on the team's score on /scoreboard"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db, name="user")
|
||||
team = gen_team(app.db)
|
||||
user.team_id = team.id
|
||||
team.members.append(user)
|
||||
gen_challenge(app.db)
|
||||
gen_flag(app.db, 1)
|
||||
app.db.session.commit()
|
||||
with login_as_user(app) as client:
|
||||
flag = {"challenge_id": 1, "submission": "flag"}
|
||||
client.post("/api/v1/challenges/attempt", json=flag)
|
||||
standings = get_standings()
|
||||
assert standings[0].name == "team_name"
|
||||
assert standings[0].score == 100
|
||||
destroy_ctfd(app)
|
||||
251
tests/teams/test_teams.py
Normal file
251
tests/teams/test_teams.py
Normal file
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from CTFd.models import Teams, Users
|
||||
from CTFd.utils import set_config
|
||||
from tests.helpers import (
|
||||
create_ctfd,
|
||||
destroy_ctfd,
|
||||
gen_award,
|
||||
gen_team,
|
||||
gen_user,
|
||||
login_as_user,
|
||||
register_user,
|
||||
)
|
||||
|
||||
|
||||
def test_teams_get():
|
||||
"""Can a user get /teams"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
with app.test_client() as client:
|
||||
set_config("account_visibility", "public")
|
||||
r = client.get("/teams")
|
||||
assert r.status_code == 200
|
||||
set_config("account_visibility", "private")
|
||||
r = client.get("/teams")
|
||||
assert r.status_code == 302
|
||||
set_config("account_visibility", "admins")
|
||||
r = client.get("/teams")
|
||||
assert r.status_code == 404
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_accessing_hidden_teams():
|
||||
"""Hidden teams should not give any data from /teams or /api/v1/teams"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
register_user(app, name="visible_user", email="visible_user@examplectf.com")
|
||||
with login_as_user(app, name="visible_user") as client:
|
||||
user = Users.query.filter_by(id=2).first()
|
||||
team = gen_team(app.db, name="visible_team", hidden=True)
|
||||
team.members.append(user)
|
||||
user.team_id = team.id
|
||||
app.db.session.commit()
|
||||
|
||||
assert client.get("/teams/1").status_code == 404
|
||||
assert client.get("/api/v1/teams/1").status_code == 404
|
||||
assert client.get("/api/v1/teams/1/solves").status_code == 404
|
||||
assert client.get("/api/v1/teams/1/fails").status_code == 404
|
||||
assert client.get("/api/v1/teams/1/awards").status_code == 404
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_hidden_teams_visibility():
|
||||
"""Hidden teams should not show up on /teams or /api/v1/teams or /api/v1/scoreboard"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
user = Users.query.filter_by(id=2).first()
|
||||
user_id = user.id
|
||||
team = gen_team(app.db, name="visible_team", hidden=True)
|
||||
team_id = team.id
|
||||
team_name = team.name
|
||||
team.members.append(user)
|
||||
user.team_id = team.id
|
||||
app.db.session.commit()
|
||||
|
||||
r = client.get("/teams")
|
||||
response = r.get_data(as_text=True)
|
||||
# Only search in body content
|
||||
body_start = response.find("<body>")
|
||||
body_end = response.find("</body>")
|
||||
response = response[body_start:body_end]
|
||||
assert team_name not in response
|
||||
|
||||
r = client.get("/api/v1/teams")
|
||||
response = r.get_json()
|
||||
assert team_name not in response
|
||||
|
||||
gen_award(app.db, user_id, team_id=team_id)
|
||||
|
||||
r = client.get("/scoreboard")
|
||||
response = r.get_data(as_text=True)
|
||||
# Only search in body content
|
||||
body_start = response.find("<body>")
|
||||
body_end = response.find("</body>")
|
||||
response = response[body_start:body_end]
|
||||
assert team_name not in response
|
||||
|
||||
r = client.get("/api/v1/scoreboard")
|
||||
response = r.get_json()
|
||||
assert team_name not in response
|
||||
|
||||
# Team should re-appear after disabling hiding
|
||||
# Use an API call to cause a cache clear
|
||||
with login_as_user(app, name="admin") as admin:
|
||||
r = admin.patch("/api/v1/teams/1", json={"hidden": False})
|
||||
assert r.status_code == 200
|
||||
|
||||
r = client.get("/teams")
|
||||
response = r.get_data(as_text=True)
|
||||
assert team_name in response
|
||||
|
||||
r = client.get("/api/v1/teams")
|
||||
response = r.get_data(as_text=True)
|
||||
assert team_name in response
|
||||
|
||||
r = client.get("/api/v1/scoreboard")
|
||||
response = r.get_data(as_text=True)
|
||||
assert team_name in response
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_get_user_mode():
|
||||
"""Can a user get /teams if user mode"""
|
||||
app = create_ctfd(user_mode="users")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams")
|
||||
assert r.status_code == 404
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_get():
|
||||
"""Can a user get /team"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db)
|
||||
team = gen_team(app.db)
|
||||
team.members.append(user)
|
||||
user.team_id = team.id
|
||||
app.db.session.commit()
|
||||
with login_as_user(app, name="user_name", password="password") as client:
|
||||
r = client.get("/team")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_teams_id_get():
|
||||
"""Can a user get /teams/<int:team_id>"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
user = gen_user(app.db)
|
||||
team = gen_team(app.db)
|
||||
team.members.append(user)
|
||||
user.team_id = team.id
|
||||
app.db.session.commit()
|
||||
with login_as_user(app, name="user_name", password="password") as client:
|
||||
r = client.get("/teams/1")
|
||||
assert r.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_size_limit():
|
||||
"""Only team_size amount of members can join a team"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
set_config("team_size", 1)
|
||||
|
||||
# Create a team with only one member
|
||||
team = gen_team(app.db, member_count=1)
|
||||
team_id = team.id
|
||||
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/join")
|
||||
assert r.status_code == 200
|
||||
|
||||
# User should be blocked from joining
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team_name",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/join", data=data)
|
||||
resp = r.get_data(as_text=True)
|
||||
assert len(Teams.query.filter_by(id=team_id).first().members) == 1
|
||||
assert "already reached the team size limit of 1" in resp
|
||||
|
||||
# Can the user join after the size has been bumped
|
||||
set_config("team_size", 2)
|
||||
r = client.post("/teams/join", data=data)
|
||||
resp = r.get_data(as_text=True)
|
||||
assert len(Teams.query.filter_by(id=team_id).first().members) == 2
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_num_teams_limit():
|
||||
"""Only num_teams teams can be created"""
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
set_config("num_teams", 1)
|
||||
|
||||
# Create a team
|
||||
gen_team(app.db, member_count=1)
|
||||
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
r = client.get("/teams/new")
|
||||
assert r.status_code == 403
|
||||
|
||||
# team should be blocked from creation
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team1",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
resp = r.get_data(as_text=True)
|
||||
assert Teams.query.count() == 1
|
||||
assert "Reached the maximum number of teams" in resp
|
||||
|
||||
# Can the team be created after the num has been bumped
|
||||
set_config("num_teams", 2)
|
||||
r = client.post("/teams/new", data=data)
|
||||
resp = r.get_data(as_text=True)
|
||||
assert Teams.query.count() == 2
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_team_creation_disable():
|
||||
app = create_ctfd(user_mode="teams")
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
with login_as_user(app) as client:
|
||||
# Team creation page should be available
|
||||
r = client.get("/teams/new")
|
||||
assert r.status_code == 200
|
||||
|
||||
# Disable team creation in config
|
||||
set_config("team_creation", False)
|
||||
|
||||
# Can't access the public team creation page
|
||||
r = client.get("/teams/new")
|
||||
assert r.status_code == 403
|
||||
|
||||
# User should be blocked from creating teams as well
|
||||
with client.session_transaction() as sess:
|
||||
data = {
|
||||
"name": "team_name",
|
||||
"password": "password",
|
||||
"nonce": sess.get("nonce"),
|
||||
}
|
||||
r = client.post("/teams/new", data=data)
|
||||
assert r.status_code == 403
|
||||
destroy_ctfd(app)
|
||||
Reference in New Issue
Block a user