mirror of https://github.com/JohnHammond/CTFd.git
Re add view after ctf (#774)
* Re-add view_after_ctf configuration * Add test for view_after_ctf functionalityselenium-screenshot-testing
parent
66c749fce6
commit
5a14cc2040
|
@ -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 ctftime, ctf_started, ctf_paused, ctf_ended, unix_time, unix_time_to_utc
|
||||
from CTFd.utils.dates import ctf_paused, view_after_ctf
|
||||
from CTFd.utils.helpers import get_errors, get_infos
|
||||
|
||||
challenges = Blueprint('challenges', __name__)
|
||||
|
@ -30,11 +30,7 @@ def listing():
|
|||
if ctf_paused():
|
||||
infos.append('{} is paused'.format(config.ctf_name()))
|
||||
|
||||
if not ctftime():
|
||||
if ctf_started() is False:
|
||||
errors.append('{} has not started yet'.format(config.ctf_name()))
|
||||
if ctf_ended():
|
||||
errors.append('{} has ended'.format(config.ctf_name()))
|
||||
return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end))
|
||||
if 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))
|
||||
|
|
|
@ -2,15 +2,19 @@
|
|||
<form method="POST" autocomplete="off" class="w-100">
|
||||
<ul class="nav nav-tabs mb-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#start-date" aria-controls="start-date" role="tab" data-toggle="tab">Start
|
||||
Time</a>
|
||||
<a class="nav-link active" href="#start-date" aria-controls="start-date" role="tab" data-toggle="tab">
|
||||
Start Time
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#end-date" aria-controls="end-date" role="tab" data-toggle="tab">End Time</a>
|
||||
<a class="nav-link" href="#end-date" aria-controls="end-date" role="tab" data-toggle="tab">
|
||||
End Time
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#freeze-date" aria-controls="freeze-date" role="tab" data-toggle="tab">Freeze
|
||||
Time</a>
|
||||
<a class="nav-link" href="#freeze-date" aria-controls="freeze-date" role="tab" data-toggle="tab">
|
||||
Freeze Time
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -122,6 +126,14 @@
|
|||
max="59" type='number'>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label>
|
||||
<input id="view_after_ctf" name="view_after_ctf" type="checkbox"
|
||||
{% if view_after_ctf %}checked{% endif %}>
|
||||
Allow challenges to be viewed (no submissions are recorded) after the CTF End Time.
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="end-timezone">Timezone:</label>
|
||||
<select class="form-control end-date" id="end-timezone">
|
||||
|
|
|
@ -53,6 +53,10 @@ def ctf_ended():
|
|||
return False
|
||||
|
||||
|
||||
def view_after_ctf():
|
||||
return get_config('view_after_ctf')
|
||||
|
||||
|
||||
def unix_time(dt):
|
||||
return int((dt - datetime.datetime(1970, 1, 1)).total_seconds())
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from flask import request, redirect, url_for, session, abort, jsonify
|
||||
from CTFd.utils import config, get_config, get_app_config
|
||||
from CTFd.cache import cache
|
||||
from CTFd.utils.dates import ctf_ended, ctf_paused, ctf_started, ctftime
|
||||
from CTFd.utils.dates import ctf_ended, ctf_paused, ctf_started, ctftime, view_after_ctf
|
||||
from CTFd.utils import user as current_user
|
||||
from CTFd.utils.user import get_current_user, get_current_team, is_admin, authed
|
||||
from CTFd.utils.modes import TEAMS_MODE, USERS_MODE
|
||||
|
@ -21,9 +21,11 @@ def during_ctf_time_only(f):
|
|||
return f(*args, **kwargs)
|
||||
else:
|
||||
if ctf_ended():
|
||||
if view_after_ctf():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
error = '{} has ended'.format(config.ctf_name())
|
||||
abort(403, description=error)
|
||||
|
||||
if ctf_started() is False:
|
||||
error = '{} has not started yet'.format(config.ctf_name())
|
||||
abort(403, description=error)
|
||||
|
|
|
@ -507,3 +507,78 @@ def test_challenges_cannot_be_solved_while_paused():
|
|||
wrong_keys = Fails.query.count()
|
||||
assert wrong_keys == 0
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_challenges_under_view_after_ctf():
|
||||
app = create_ctfd()
|
||||
with app.app_context(), freeze_time("2017-10-7"):
|
||||
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')
|
||||
|
||||
r = client.get('/challenges')
|
||||
assert r.status_code == 403
|
||||
|
||||
r = client.get('/api/v1/challenges')
|
||||
assert r.status_code == 403
|
||||
assert r.get_json().get('data') is None
|
||||
|
||||
r = client.get('/api/v1/challenges/1')
|
||||
assert r.status_code == 403
|
||||
assert r.get_json().get('data') is None
|
||||
|
||||
data = {
|
||||
"submission": 'flag',
|
||||
"challenge_id": 1
|
||||
}
|
||||
r = client.post('/api/v1/challenges/attempt', json=data)
|
||||
assert r.status_code == 403
|
||||
assert r.get_json().get('data') is None
|
||||
assert Solves.query.count() == 0
|
||||
|
||||
data = {
|
||||
"submission": 'notflag',
|
||||
"challenge_id": 1
|
||||
}
|
||||
r = client.post('/api/v1/challenges/attempt', json=data)
|
||||
assert r.status_code == 403
|
||||
assert r.get_json().get('data') is None
|
||||
assert Fails.query.count() == 0
|
||||
|
||||
set_config('view_after_ctf', True)
|
||||
|
||||
r = client.get('/challenges')
|
||||
assert r.status_code == 200
|
||||
|
||||
r = client.get('/api/v1/challenges')
|
||||
assert r.status_code == 200
|
||||
assert r.get_json()['data'][0]['id'] == 1
|
||||
|
||||
r = client.get('/api/v1/challenges/1')
|
||||
assert r.status_code == 200
|
||||
assert r.get_json()['data']['id'] == 1
|
||||
|
||||
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() == 0
|
||||
|
||||
data = {
|
||||
"submission": 'notflag',
|
||||
"challenge_id": 1
|
||||
}
|
||||
r = client.post('/api/v1/challenges/attempt', json=data)
|
||||
assert r.status_code == 200
|
||||
assert r.get_json()['data']['status'] == "incorrect"
|
||||
assert Fails.query.count() == 0
|
||||
|
||||
destroy_ctfd(app)
|
||||
|
|
Loading…
Reference in New Issue