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.decorators.visibility import check_challenge_visibility
|
||||||
from CTFd.utils import config, text_type, user as current_user, get_config
|
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
|
from CTFd.utils.helpers import get_errors, get_infos
|
||||||
|
|
||||||
challenges = Blueprint('challenges', __name__)
|
challenges = Blueprint('challenges', __name__)
|
||||||
|
@ -30,11 +30,7 @@ def listing():
|
||||||
if ctf_paused():
|
if ctf_paused():
|
||||||
infos.append('{} is paused'.format(config.ctf_name()))
|
infos.append('{} is paused'.format(config.ctf_name()))
|
||||||
|
|
||||||
if not ctftime():
|
if view_after_ctf():
|
||||||
if ctf_started() is False:
|
infos.append('{} has ended'.format(config.ctf_name()))
|
||||||
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))
|
|
||||||
|
|
||||||
return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end))
|
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">
|
<form method="POST" autocomplete="off" class="w-100">
|
||||||
<ul class="nav nav-tabs mb-3">
|
<ul class="nav nav-tabs mb-3">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" href="#start-date" aria-controls="start-date" role="tab" data-toggle="tab">Start
|
<a class="nav-link active" href="#start-date" aria-controls="start-date" role="tab" data-toggle="tab">
|
||||||
Time</a>
|
Start Time
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<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>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="#freeze-date" aria-controls="freeze-date" role="tab" data-toggle="tab">Freeze
|
<a class="nav-link" href="#freeze-date" aria-controls="freeze-date" role="tab" data-toggle="tab">
|
||||||
Time</a>
|
Freeze Time
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -122,6 +126,14 @@
|
||||||
max="59" type='number'>
|
max="59" type='number'>
|
||||||
</div>
|
</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">
|
<div class="form-group col-md-12">
|
||||||
<label for="end-timezone">Timezone:</label>
|
<label for="end-timezone">Timezone:</label>
|
||||||
<select class="form-control end-date" id="end-timezone">
|
<select class="form-control end-date" id="end-timezone">
|
||||||
|
|
|
@ -53,6 +53,10 @@ def ctf_ended():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def view_after_ctf():
|
||||||
|
return get_config('view_after_ctf')
|
||||||
|
|
||||||
|
|
||||||
def unix_time(dt):
|
def unix_time(dt):
|
||||||
return int((dt - datetime.datetime(1970, 1, 1)).total_seconds())
|
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 flask import request, redirect, url_for, session, abort, jsonify
|
||||||
from CTFd.utils import config, get_config, get_app_config
|
from CTFd.utils import config, get_config, get_app_config
|
||||||
from CTFd.cache import cache
|
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 import user as current_user
|
||||||
from CTFd.utils.user import get_current_user, get_current_team, is_admin, authed
|
from CTFd.utils.user import get_current_user, get_current_team, is_admin, authed
|
||||||
from CTFd.utils.modes import TEAMS_MODE, USERS_MODE
|
from CTFd.utils.modes import TEAMS_MODE, USERS_MODE
|
||||||
|
@ -21,9 +21,11 @@ def during_ctf_time_only(f):
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
else:
|
else:
|
||||||
if ctf_ended():
|
if ctf_ended():
|
||||||
|
if view_after_ctf():
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
else:
|
||||||
error = '{} has ended'.format(config.ctf_name())
|
error = '{} has ended'.format(config.ctf_name())
|
||||||
abort(403, description=error)
|
abort(403, description=error)
|
||||||
|
|
||||||
if ctf_started() is False:
|
if ctf_started() is False:
|
||||||
error = '{} has not started yet'.format(config.ctf_name())
|
error = '{} has not started yet'.format(config.ctf_name())
|
||||||
abort(403, description=error)
|
abort(403, description=error)
|
||||||
|
|
|
@ -507,3 +507,78 @@ def test_challenges_cannot_be_solved_while_paused():
|
||||||
wrong_keys = Fails.query.count()
|
wrong_keys = Fails.query.count()
|
||||||
assert wrong_keys == 0
|
assert wrong_keys == 0
|
||||||
destroy_ctfd(app)
|
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