Files
CTFd/tests/api/v1/challenges/requirements/test_requirements.py
Kevin Chung d23f59dbd5 Fix issue where admins couldn't see some challenges in the add requirements interface (#1853)
- Fix an issue where admins couldn't see challenges which had requirements in the add requirements interface
2021-03-27 19:59:10 -04:00

172 lines
6.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from CTFd.models import Users
from CTFd.utils import set_config
from tests.helpers import (
create_ctfd,
destroy_ctfd,
gen_challenge,
gen_solve,
login_as_user,
register_user,
)
def test_api_challenges_admins_can_bypass_requirements():
"""Test that admins can bypass requirements checks with admin capabilities and view-admin"""
app = create_ctfd()
with app.app_context():
# Create challenges
prereq_id = gen_challenge(app.db).id
chal_obj = gen_challenge(app.db)
chal_obj.requirements = {"prerequisites": [prereq_id]}
register_user(app)
# Confirm that regular users cannot see prerequisites
with login_as_user(app) as client:
# Locked challenges aren't shown
r = client.get("/api/v1/challenges")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 1
assert data[0]["id"] == 1
# Not even with tricks
r = client.get("/api/v1/challenges?view=admin")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 1
assert data[0]["id"] == 1
# Not even with forced browsing
r = client.get("/api/v1/challenges/2")
assert r.status_code == 403
# Confirm that admins
with login_as_user(app, name="admin") as admin:
# Admins see as regular users
r = admin.get("/api/v1/challenges")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 1
assert data[0]["id"] == 1
# Now admins can see all challenges
r = admin.get("/api/v1/challenges?view=admin")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 2
assert data[0]["id"] == 1
assert data[1]["id"] == 2
# Admins can force browse to challenges
r = admin.get("/api/v1/challenges/2")
assert r.status_code == 200
assert r.get_json()["data"]
destroy_ctfd(app)
def test_api_challenges_challenge_with_requirements():
"""Does the challenge list API show challenges with requirements met?"""
app = create_ctfd()
with app.app_context():
prereq_id = gen_challenge(app.db).id
chal_obj = gen_challenge(app.db)
chal_obj.requirements = {"prerequisites": [prereq_id]}
chal_id = chal_obj.id
# Create a new user which will solve the prerequisite
register_user(app)
# Confirm that only the prerequisite challenge is listed initially
with login_as_user(app) as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
(chal_data,) = r.get_json()["data"]
assert chal_data["id"] == prereq_id
# Generate a solve and then confirm the second challenge is visible
gen_solve(app.db, user_id=2, challenge_id=prereq_id)
with login_as_user(app) as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 2
chal_ids = {c["id"] for c in r.get_json()["data"]}
assert chal_ids == {prereq_id, chal_id}
destroy_ctfd(app)
def test_api_challenges_challenge_with_requirements_hidden_user():
"""Does the challenge list API show gated challenges to a hidden user?"""
app = create_ctfd()
with app.app_context():
prereq_id = gen_challenge(app.db).id
chal_obj = gen_challenge(app.db)
chal_obj.requirements = {"prerequisites": [prereq_id]}
chal_id = chal_obj.id
# Create a new user which will solve the prerequisite and hide them
register_user(app)
Users.query.get(2).hidden = True
app.db.session.commit()
# Confirm that only the prerequisite challenge is listed initially
with login_as_user(app) as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
(chal_data,) = r.get_json()["data"]
assert chal_data["id"] == prereq_id
# Generate a solve and then confirm the second challenge is visible
gen_solve(app.db, user_id=2, challenge_id=prereq_id)
with login_as_user(app) as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
data = r.get_json()["data"]
assert len(data) == 2
chal_ids = {c["id"] for c in r.get_json()["data"]}
assert chal_ids == {prereq_id, chal_id}
destroy_ctfd(app)
def test_api_challenges_challenge_with_requirements_banned_user():
"""Does the challenge list API show gated challenges to a banned user?"""
app = create_ctfd()
with app.app_context():
prereq_id = gen_challenge(app.db).id
chal_obj = gen_challenge(app.db)
chal_obj.requirements = {"prerequisites": [prereq_id]}
# Create a new user which will solve the prerequisite and ban them
register_user(app)
Users.query.get(2).banned = True
app.db.session.commit()
# Generate a solve just in case and confirm the API 403s
gen_solve(app.db, user_id=2, challenge_id=prereq_id)
with login_as_user(app) as client:
assert client.get("/api/v1/challenges").status_code == 403
destroy_ctfd(app)
def test_api_challenges_challenge_with_requirements_no_user():
"""Does the challenge list API show gated challenges to the public?"""
app = create_ctfd()
with app.app_context():
set_config("challenge_visibility", "public")
prereq_id = gen_challenge(app.db).id
chal_obj = gen_challenge(app.db)
chal_obj.requirements = {"prerequisites": [prereq_id]}
# Create a new user which will solve the prerequisite
register_user(app)
# Confirm that only the prerequisite challenge is listed publicly
with app.test_client() as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
initial_data = r.get_json()["data"]
(chal_data,) = initial_data
assert chal_data["id"] == prereq_id
# Fix up the solve count for later comparison with `initial_data`
chal_data["solves"] += 1
# Generate a solve and then confirm the response is unchanged
gen_solve(app.db, user_id=2, challenge_id=prereq_id)
with app.test_client() as client:
r = client.get("/api/v1/challenges")
assert r.status_code == 200
assert r.get_json()["data"] == initial_data
destroy_ctfd(app)