mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 22:14:25 +01:00
enable max-attempts per challenge setting
This commit is contained in:
@@ -71,6 +71,7 @@ def init_admin(app):
|
|||||||
ctf_name = set_config("ctf_name", request.form.get('ctf_name', None))
|
ctf_name = set_config("ctf_name", request.form.get('ctf_name', None))
|
||||||
mg_api_key = set_config("mg_api_key", request.form.get('mg_api_key', None))
|
mg_api_key = set_config("mg_api_key", request.form.get('mg_api_key', None))
|
||||||
do_api_key = set_config("do_api_key", request.form.get('do_api_key', None))
|
do_api_key = set_config("do_api_key", request.form.get('do_api_key', None))
|
||||||
|
max_tries = set_config("max_tries", request.form.get('max_tries', None))
|
||||||
|
|
||||||
db_start = Config.query.filter_by(key='start').first()
|
db_start = Config.query.filter_by(key='start').first()
|
||||||
db_start.value = start
|
db_start.value = start
|
||||||
@@ -96,6 +97,11 @@ def init_admin(app):
|
|||||||
if not do_api_key:
|
if not do_api_key:
|
||||||
set_config('do_api_key', None)
|
set_config('do_api_key', None)
|
||||||
|
|
||||||
|
max_tries = get_config('max_tries')
|
||||||
|
if not max_tries:
|
||||||
|
set_config('max_tries', 0)
|
||||||
|
max_tries = 0
|
||||||
|
|
||||||
start = get_config('start')
|
start = get_config('start')
|
||||||
if not start:
|
if not start:
|
||||||
set_config('start', None)
|
set_config('start', None)
|
||||||
@@ -120,6 +126,7 @@ def init_admin(app):
|
|||||||
db.session.close()
|
db.session.close()
|
||||||
|
|
||||||
return render_template('admin/config.html', ctf_name=ctf_name, start=start, end=end,
|
return render_template('admin/config.html', ctf_name=ctf_name, start=start, end=end,
|
||||||
|
max_tries=max_tries,
|
||||||
view_challenges_unregistered=view_challenges_unregistered,
|
view_challenges_unregistered=view_challenges_unregistered,
|
||||||
prevent_registration=prevent_registration, do_api_key=do_api_key, mg_api_key=mg_api_key,
|
prevent_registration=prevent_registration, do_api_key=do_api_key, mg_api_key=mg_api_key,
|
||||||
prevent_name_change=prevent_name_change)
|
prevent_name_change=prevent_name_change)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from flask import current_app as app, render_template, request, redirect, abort, jsonify, json as json_mod, url_for, session
|
from flask import current_app as app, render_template, request, redirect, abort, jsonify, json as json_mod, url_for, session
|
||||||
|
|
||||||
from CTFd.utils import ctftime, authed, unix_time, get_kpm, can_view_challenges, is_admin
|
from CTFd.utils import ctftime, authed, unix_time, get_kpm, can_view_challenges, is_admin, get_config
|
||||||
from CTFd.models import db, Challenges, Files, Solves, WrongKeys, Keys
|
from CTFd.models import db, Challenges, Files, Solves, WrongKeys, Keys
|
||||||
|
|
||||||
import time
|
import time
|
||||||
@@ -58,7 +58,17 @@ def init_challenges(app):
|
|||||||
db.session.close()
|
db.session.close()
|
||||||
json = {'solves':[]}
|
json = {'solves':[]}
|
||||||
for x in solves:
|
for x in solves:
|
||||||
json['solves'].append({'id':x.id, 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)})
|
json['solves'].append({ 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)})
|
||||||
|
return jsonify(json)
|
||||||
|
|
||||||
|
@app.route('/maxattempts')
|
||||||
|
def attempts():
|
||||||
|
chals = Challenges.query.add_columns('id').all()
|
||||||
|
json = {'maxattempts':[]}
|
||||||
|
for chal, chalid in chals:
|
||||||
|
fails = WrongKeys.query.filter_by(team=session['id'], chal=chalid).count()
|
||||||
|
if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
|
||||||
|
json['maxattempts'].append({'chalid':chalid})
|
||||||
return jsonify(json)
|
return jsonify(json)
|
||||||
|
|
||||||
@app.route('/fails/<teamid>', methods=['GET'])
|
@app.route('/fails/<teamid>', methods=['GET'])
|
||||||
@@ -82,9 +92,12 @@ def init_challenges(app):
|
|||||||
if not ctftime():
|
if not ctftime():
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
if authed():
|
if authed():
|
||||||
|
fails = WrongKeys.query.filter_by(team=session['id'],chal=chalid).count()
|
||||||
logger = logging.getLogger('keys')
|
logger = logging.getLogger('keys')
|
||||||
data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
|
data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
|
||||||
print "[{0}] {1} submitted {2} with kpm {3}".format(*data)
|
print "[{0}] {1} submitted {2} with kpm {3}".format(*data)
|
||||||
|
if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
|
||||||
|
return "4" #too many tries on this challenge
|
||||||
if get_kpm(session['id']) > 10:
|
if get_kpm(session['id']) > 10:
|
||||||
wrong = WrongKeys(session['id'], chalid, request.form['key'])
|
wrong = WrongKeys(session['id'], chalid, request.form['key'])
|
||||||
db.session.add(wrong)
|
db.session.add(wrong)
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ def init_views(app):
|
|||||||
html = request.form['html']
|
html = request.form['html']
|
||||||
page = Pages('index', html)
|
page = Pages('index', html)
|
||||||
|
|
||||||
|
#max attempts per challenge
|
||||||
|
max_tries = Config("max_tries",0)
|
||||||
|
|
||||||
|
|
||||||
## Start time
|
## Start time
|
||||||
start = Config('start', None)
|
start = Config('start', None)
|
||||||
end = Config('end', None)
|
end = Config('end', None)
|
||||||
@@ -77,6 +81,7 @@ def init_views(app):
|
|||||||
db.session.add(ctf_name)
|
db.session.add(ctf_name)
|
||||||
db.session.add(admin)
|
db.session.add(admin)
|
||||||
db.session.add(page)
|
db.session.add(page)
|
||||||
|
db.session.add(max_tries)
|
||||||
db.session.add(start)
|
db.session.add(start)
|
||||||
db.session.add(end)
|
db.session.add(end)
|
||||||
db.session.add(view_challenges_unregistered)
|
db.session.add(view_challenges_unregistered)
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ function submitkey(chal, key, nonce) {
|
|||||||
$('#submit-key').css('background-color', '#e18728')
|
$('#submit-key').css('background-color', '#e18728')
|
||||||
$('#submit-key').prop('disabled', true)
|
$('#submit-key').prop('disabled', true)
|
||||||
}
|
}
|
||||||
|
else if (data == 4){ // too many incorrect solves
|
||||||
|
$('#submit-key').text('Too many attempts.')
|
||||||
|
$('#submit-key').css('background-color', 'red')
|
||||||
|
$('#submit-key').prop('disabled', true)
|
||||||
|
}
|
||||||
|
marktoomanyattempts()
|
||||||
marksolves()
|
marksolves()
|
||||||
updatesolves()
|
updatesolves()
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
@@ -129,6 +135,20 @@ function marksolves() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function marktoomanyattempts() {
|
||||||
|
$.get('/maxattempts', function (data) {
|
||||||
|
maxattempts = $.parseJSON(JSON.stringify(data));
|
||||||
|
for (var i = maxattempts['maxattempts'].length - 1; i >= 0; i--) {
|
||||||
|
id = maxattempts['maxattempts'][i].chalid
|
||||||
|
$('#challenges button[value="' + id + '"]').addClass('secondary')
|
||||||
|
$('#challenges button[value="' + id + '"]').css('background-color', '#FF9999')
|
||||||
|
};
|
||||||
|
if (window.location.hash.length > 0){
|
||||||
|
loadchalbyname(window.location.hash.substring(1))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function updatesolves(){
|
function updatesolves(){
|
||||||
$.get('/chals/solves', function (data) {
|
$.get('/chals/solves', function (data) {
|
||||||
solves = $.parseJSON(JSON.stringify(data));
|
solves = $.parseJSON(JSON.stringify(data));
|
||||||
@@ -177,6 +197,7 @@ function loadchals() {
|
|||||||
$('#' + challenges['game'][i].category.replace(/ /g,"-")).append($('<button value="' + challenges['game'][i].id + '">' + challenges['game'][i].value + '</button>'));
|
$('#' + challenges['game'][i].category.replace(/ /g,"-")).append($('<button value="' + challenges['game'][i].id + '">' + challenges['game'][i].value + '</button>'));
|
||||||
};
|
};
|
||||||
updatesolves()
|
updatesolves()
|
||||||
|
marktoomanyattempts()
|
||||||
marksolves()
|
marksolves()
|
||||||
|
|
||||||
$('#challenges button').click(function (e) {
|
$('#challenges button').click(function (e) {
|
||||||
|
|||||||
@@ -12,6 +12,11 @@
|
|||||||
<input id='ctf_name' name='ctf_name' type='text' placeholder="CTF Name" {% if ctf_name is defined and ctf_name != None %}value="{{ ctf_name }}"{% endif %}>
|
<input id='ctf_name' name='ctf_name' type='text' placeholder="CTF Name" {% if ctf_name is defined and ctf_name != None %}value="{{ ctf_name }}"{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<label for="max_tries">Maximum Attempts Per Challenge (0 to disable):</label>
|
||||||
|
<input id='max_tries' name='max_tries' type='text' placeholder="0" {% if max_tries is defined and max_tries != None %}value="{{ max_tries }}"{% endif %}>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for="start">Mailgun API Key:</label>
|
<label for="start">Mailgun API Key:</label>
|
||||||
<input id='mg_api_key' name='mg_api_key' type='text' placeholder="Mailgun API Key" {% if mg_api_key is defined and mg_api_key != None %}value="{{ mg_api_key }}"{% endif %}>
|
<input id='mg_api_key' name='mg_api_key' type='text' placeholder="Mailgun API Key" {% if mg_api_key is defined and mg_api_key != None %}value="{{ mg_api_key }}"{% endif %}>
|
||||||
|
|||||||
Reference in New Issue
Block a user