diff --git a/CTFd/challenges.py b/CTFd/challenges.py index d2a2b6d2..30ef0cf2 100644 --- a/CTFd/challenges.py +++ b/CTFd/challenges.py @@ -10,7 +10,7 @@ from CTFd.utils.decorators import ( ) from CTFd.utils.decorators.visibility import check_challenge_visibility from CTFd.utils import config, text_type, user as current_user, get_config -from CTFd.utils.dates import ctf_paused, view_after_ctf +from CTFd.utils.dates import ctf_paused, view_after_ctf, ctf_ended from CTFd.utils.helpers import get_errors, get_infos challenges = Blueprint('challenges', __name__) @@ -30,7 +30,8 @@ def listing(): if ctf_paused(): infos.append('{} is paused'.format(config.ctf_name())) - if view_after_ctf(): + # CTF has ended but we want to allow view_after_ctf. Show error but let JS load challenges. + if ctf_ended() and view_after_ctf(): infos.append('{} has ended'.format(config.ctf_name())) return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end)) diff --git a/tests/users/test_challenges.py b/tests/users/test_challenges.py index d6f83355..a1b2f5ca 100644 --- a/tests/users/test_challenges.py +++ b/tests/users/test_challenges.py @@ -503,6 +503,55 @@ def test_challenges_cannot_be_solved_while_paused(): destroy_ctfd(app) +def test_challenge_board_under_view_after_ctf(): + """Test that the challenge board does not show an error under view_after_ctf""" + app = create_ctfd() + with app.app_context(): + set_config('view_after_ctf', True) + set_config('start', '1507089600') # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST + set_config('end', '1507262400') # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST + + register_user(app) + client = login_as_user(app) + + gen_challenge(app.db) + gen_flag(app.db, challenge_id=1, content='flag') + + gen_challenge(app.db) + gen_flag(app.db, challenge_id=2, content='flag') + + # CTF is ongoing. Normal operation. + with freeze_time("2017-10-5"): + r = client.get('/challenges') + assert r.status_code == 200 + assert "has ended" not in r.get_data(as_text=True) + + data = { + "submission": 'flag', + "challenge_id": 1 + } + r = client.post('/api/v1/challenges/attempt', json=data) + assert r.status_code == 200 + assert r.get_json()['data']['status'] == "correct" + assert Solves.query.count() == 1 + + # CTF is now over. There should be a message and challenges should show submission status but not store solves + with freeze_time("2017-10-7"): + r = client.get('/challenges') + assert r.status_code == 200 + assert "has ended" in r.get_data(as_text=True) + + data = { + "submission": 'flag', + "challenge_id": 2 + } + r = client.post('/api/v1/challenges/attempt', json=data) + assert r.status_code == 200 + assert r.get_json()['data']['status'] == "correct" + assert Solves.query.count() == 1 + destroy_ctfd(app) + + def test_challenges_under_view_after_ctf(): app = create_ctfd() with app.app_context(), freeze_time("2017-10-7"):