diff --git a/.gitignore b/.gitignore index 54707f74..ce8bcb3b 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,4 @@ CTFd/static/uploads CTFd/uploads .data/ .ctfd_secret_key +.*.swp diff --git a/CTFd/admin/challenges.py b/CTFd/admin/challenges.py index 8b733bcd..562bfaba 100644 --- a/CTFd/admin/challenges.py +++ b/CTFd/admin/challenges.py @@ -25,7 +25,7 @@ def admin_chal_types(): @admins_only def admin_chals(): if request.method == 'POST': - chals = Challenges.query.add_columns('id', 'name', 'value', 'description', 'category', 'hidden', 'max_attempts').order_by(Challenges.value).all() + chals = Challenges.query.add_columns('id', 'type', 'name', 'value', 'description', 'category', 'hidden', 'max_attempts').order_by(Challenges.value).all() teams_with_points = db.session.query(Solves.teamid).join(Teams).filter( Teams.banned == False).group_by(Solves.teamid).count() @@ -39,6 +39,9 @@ def admin_chals(): else: percentage = 0.0 + type_class = CHALLENGE_CLASSES.get(x.type) + type_name = type_class.name if type_class else None + json_data['game'].append({ 'id': x.id, 'name': x.name, @@ -47,6 +50,8 @@ def admin_chals(): 'category': x.category, 'hidden': x.hidden, 'max_attempts': x.max_attempts, + 'type': x.type, + 'type_name': type_name, 'percentage_solved': percentage }) @@ -286,4 +291,4 @@ def admin_update_chal(): db.session.add(challenge) db.session.commit() db.session.close() - return redirect(url_for('admin_challenges.admin_chals')) \ No newline at end of file + return redirect(url_for('admin_challenges.admin_chals')) diff --git a/CTFd/static/admin/js/chal-new.js b/CTFd/static/admin/js/chal-new.js new file mode 100644 index 00000000..b56b1bf1 --- /dev/null +++ b/CTFd/static/admin/js/chal-new.js @@ -0,0 +1,33 @@ +function load_chal_template(chal_type_name){ + $.get(script_root + '/static/admin/js/templates/challenges/'+ chal_type_name +'/' + chal_type_name + '-challenge-create.hbs', function(template_data){ + var template = Handlebars.compile(template_data); + $("#create-chal-entry-div").html(template({'nonce':nonce, 'script_root':script_root})); + $.getScript(script_root + '/static/admin/js/templates/challenges/'+chal_type_name+'/'+chal_type_name+'-challenge-create.js', function(){ + console.log('loaded'); + }); + }); +} + + +nonce = "{{ nonce }}"; +$.get(script_root + '/admin/chal_types', function(data){ + console.log(data); + $("#create-chals-select").empty(); + var chal_type_amt = Object.keys(data).length; + if (chal_type_amt > 1){ + var option = ""; + $("#create-chals-select").append(option); + for (var key in data){ + var option = "".format(key, data[key]); + $("#create-chals-select").append(option); + } + } else if (chal_type_amt == 1) { + var key = Object.keys(data)[0]; + $("#create-chals-select").parent().parent().parent().empty(); + load_chal_template(data[key]); + } +}); +$('#create-chals-select').change(function(){ + var chal_type_name = $(this).find("option:selected").text(); + load_chal_template(chal_type_name); +}); diff --git a/CTFd/static/admin/js/chalboard.js b/CTFd/static/admin/js/chalboard.js index 8a4c5f5b..71deb52d 100644 --- a/CTFd/static/admin/js/chalboard.js +++ b/CTFd/static/admin/js/chalboard.js @@ -38,255 +38,25 @@ function load_edit_key_modal(key_id, key_type_name) { }); } -function load_hint_modal(method, hintid){ - $('#hint-modal-hint').val(''); - $('#hint-modal-cost').val(''); - if (method == 'create'){ - $('#hint-modal-submit').attr('action', '/admin/hints'); - $('#hint-modal-title').text('Create Hint'); - $("#hint-modal").modal(); - } else if (method == 'update'){ - $.get(script_root + '/admin/hints/' + hintid, function(data){ - $('#hint-modal-submit').attr('action', '/admin/hints/' + hintid); - $('#hint-modal-hint').val(data.hint); - $('#hint-modal-cost').val(data.cost); - $('#hint-modal-title').text('Update Hint'); - $("#hint-modal-button").text('Update Hint'); - $("#hint-modal").modal(); - }); - } -} - -function loadchal(id, update) { - // $('#chal *').show() - // $('#chal > h1').hide() +function load_chal_template(id, success_cb){ obj = $.grep(challenges['game'], function (e) { return e.id == id; })[0] - $('#desc-write-link').click() // Switch to Write tab - $('.chal-title').text(obj.name); - $('.chal-name').val(obj.name); - $('.chal-desc').val(obj.description); - $('.chal-value').val(obj.value); - if (parseInt(obj.max_attempts) > 0){ - $('.chal-attempts').val(obj.max_attempts); - $('#limit_max_attempts').prop('checked', true); - $('#chal-attempts-group').show(); - } - $('.chal-category').val(obj.category); - $('.chal-id').val(obj.id); - $('.chal-hidden').prop('checked', false); - if (obj.hidden) { - $('.chal-hidden').prop('checked', true); - } - //$('#update-challenge .chal-delete').attr({ - // 'href': '/admin/chal/close/' + (id + 1) - //}) - if (typeof update === 'undefined') - $('#update-challenge').modal(); -} - -function submitkey(chal, key) { - $.post(script_root + "/admin/chal/" + chal, { - key: key, - nonce: $('#nonce').val() - }, function (data) { - alert(data) - }) -} - -function create_key(chal, key, key_type) { - $.post(script_root + "/admin/keys", { - chal: chal, - key: key, - key_type: key_type, - nonce: $('#nonce').val() - }, function (data) { - if (data == "1"){ - loadkeys(chal); - $("#create-keys").modal('toggle'); - } - }); -} - -function loadkeys(chal){ - $.get(script_root + '/admin/chal/' + chal + '/keys', function(data){ - $('#keys-chal').val(chal); - keys = $.parseJSON(JSON.stringify(data)); - keys = keys['keys']; - $('#current-keys').empty(); - $.get(script_root + "/static/admin/js/templates/admin-keys-table.hbs", function(data){ - var template = Handlebars.compile(data); - var wrapper = {keys: keys, script_root: script_root}; - $('#current-keys').append(template(wrapper)); + $.get(script_root + '/static/admin/js/templates/challenges/'+ obj['type_name'] +'/' + obj['type_name'] + '-challenge-update.hbs', function(template_data){ + var template = Handlebars.compile(template_data); + $.get(script_root + '/static/admin/js/templates/challenges/'+ obj['type_name'] +'/' + obj['type_name'] + '-challenge-modals.hbs', function(template_data){ + var template = Handlebars.compile(template_data); + $("#update-modals-entry-div").html(template({'nonce':$('#nonce').val(), 'script_root':script_root})); + }); + $.ajax({ + url: script_root + '/static/admin/js/templates/challenges/'+obj['type_name']+'/'+obj['type_name']+'-challenge-update.js', + dataType: "script", + success: success_cb, + cache: true, }); }); } -function updatekeys(){ - keys = []; - vals = []; - chal = $('#keys-chal').val() - $('.current-key').each(function(){ - keys.push($(this).val()); - }) - $('#current-keys input[name*="key_type"]:checked').each(function(){ - vals.push($(this).val()); - }) - $.post(script_root + '/admin/keys/'+chal, {'keys':keys, 'vals':vals, 'nonce': $('#nonce').val()}) - loadchal(chal, true) - $('#update-keys').modal('hide'); -} - - -function deletekey(key_id){ - $.post(script_root + '/admin/keys/'+key_id+'/delete', {'nonce': $('#nonce').val()}, function(data){ - if (data == "1") { - $('tr[name={0}]'.format(key_id)).remove(); - } - }); -} - -function updatekey(){ - var key_id = $('#key-id').val(); - var chal = $('#keys-chal').val(); - var key_data = $('#key-data').val(); - var key_type = $('#key-type').val(); - var nonce = $('#nonce').val(); - $.post(script_root + '/admin/keys/'+key_id, { - 'chal':chal, - 'key':key_data, - 'key_type': key_type, - 'nonce': nonce - }, function(data){ - if (data == "1") { - loadkeys(chal); - $('#edit-keys').modal('toggle'); - } - }) -} - -function loadtags(chal){ - $('#tags-chal').val(chal) - $('#current-tags').empty() - $('#chal-tags').empty() - $.get(script_root + '/admin/tags/'+chal, function(data){ - tags = $.parseJSON(JSON.stringify(data)) - tags = tags['tags'] - for (var i = 0; i < tags.length; i++) { - tag = ""+tags[i].tag+"×" - $('#current-tags').append(tag) - }; - $('.delete-tag').click(function(e){ - deletetag(e.target.name) - $(e.target).parent().remove() - }); - }); -} - -function deletetag(tagid){ - $.post(script_root + '/admin/tags/'+tagid+'/delete', {'nonce': $('#nonce').val()}); -} - - -function edithint(hintid){ - $.get(script_root + '/admin/hints/' + hintid, function(data){ - console.log(data); - }) -} - - -function deletehint(hintid){ - $.delete(script_root + '/admin/hints/' + hintid, function(data, textStatus, jqXHR){ - if (jqXHR.status == 204){ - var chalid = $('.chal-id').val(); - loadhints(chalid); - } - }); -} - - -function loadhints(chal){ - $.get(script_root + '/admin/chal/{0}/hints'.format(chal), function(data){ - var table = $('#hintsboard > tbody'); - table.empty(); - for (var i = 0; i < data.hints.length; i++) { - var hint = data.hints[i] - var hint_row = "" + - "{0}".format(hint.hint) + - "{0}".format(hint.cost) + - "" + - "".format(hint.id)+ - "".format(hint.id)+ - "" + - ""; - table.append(hint_row); - } - }); -} - - -function deletechal(chalid){ - $.post(script_root + '/admin/chal/delete', {'nonce':$('#nonce').val(), 'id':chalid}); -} - -function updatetags(){ - tags = []; - chal = $('#tags-chal').val() - $('#chal-tags > span > span').each(function(i, e){ - tags.push($(e).text()) - }); - $.post(script_root + '/admin/tags/'+chal, {'tags':tags, 'nonce': $('#nonce').val()}) - loadchal(chal) -} - -function updatefiles(){ - chal = $('#files-chal').val(); - var form = $('#update-files form')[0]; - var formData = new FormData(form); - $.ajax({ - url: script_root + '/admin/files/'+chal, - data: formData, - type: 'POST', - cache: false, - contentType: false, - processData: false, - success: function(data){ - form.reset(); - loadfiles(chal); - $('#update-files').modal('hide'); - } - }); -} - -function loadfiles(chal){ - $('#update-files form').attr('action', script_root+'/admin/files/'+chal) - $.get(script_root + '/admin/files/' + chal, function(data){ - $('#files-chal').val(chal) - files = $.parseJSON(JSON.stringify(data)); - files = files['files'] - $('#current-files').empty() - for(x=0; x'+''+filename+'Delete') - } - }); -} - -function deletefile(chal, file, elem){ - $.post(script_root + '/admin/files/' + chal,{ - 'nonce': $('#nonce').val(), - 'method': 'delete', - 'file': file - }, function (data){ - if (data == "1") { - elem.parent().remove() - } - }); -} - - function loadchals(){ $('#challenges').empty(); $.post(script_root + "/admin/chals", { @@ -310,11 +80,10 @@ function loadchals(){ }; $('#challenges button').click(function (e) { - loadchal(this.value); - loadkeys(this.value); - loadhints(this.value); - loadtags(this.value); - loadfiles(this.value); + id = this.value + load_chal_template(id, function(){ + openchal(id); + }); }); // $('.create-challenge').click(function (e) { @@ -326,130 +95,6 @@ function loadchals(){ }); } -$('#submit-key').click(function (e) { - submitkey($('#chalid').val(), $('#answer').val()) -}); - -$('#submit-keys').click(function (e) { - e.preventDefault(); - $('#update-keys').modal('hide'); -}); - -$('#submit-tags').click(function (e) { - e.preventDefault(); - updatetags() -}); - -$('#submit-files').click(function (e) { - e.preventDefault(); - updatefiles() -}); - -$('#delete-chal form').submit(function(e){ - e.preventDefault(); - $.post(script_root + '/admin/chal/delete', $(this).serialize(), function(data){ - console.log(data) - if (data){ - loadchals(); - } - else { - alert('There was an error'); - } - }) - $("#delete-chal").modal("hide"); - $("#update-challenge").modal("hide"); -}); - -$(".tag-insert").keyup(function (e) { - if (e.keyCode == 13) { - tag = $('.tag-insert').val() - tag = tag.replace(/'/g, ''); - if (tag.length > 0){ - tag = ""+tag+"×" - $('#chal-tags').append(tag) - } - $('.tag-insert').val("") - } -}); - -$('#limit_max_attempts').change(function() { - if(this.checked) { - $('#chal-attempts-group').show(); - } else { - $('#chal-attempts-group').hide(); - $('#chal-attempts-input').val(''); - } -}); - -// Markdown Preview -$('#desc-edit').on('shown.bs.tab', function (event) { - if (event.target.hash == '#desc-preview'){ - $(event.target.hash).html(marked($('#desc-editor').val(), {'gfm':true, 'breaks':true})) - } -}); -$('#new-desc-edit').on('shown.bs.tab', function (event) { - if (event.target.hash == '#new-desc-preview'){ - $(event.target.hash).html(marked($('#new-desc-editor').val(), {'gfm':true, 'breaks':true})) - } -}); - -// Open New Challenge modal when New Challenge button is clicked -// $('.create-challenge').click(function (e) { -// $('#create-challenge').modal(); -// }); - - -$('#create-key').click(function(e){ - $.get(script_root + '/admin/key_types', function(data){ - $("#create-keys-select").empty(); - var option = ""; - $("#create-keys-select").append(option); - for (var key in data){ - var option = "".format(key, data[key]); - $("#create-keys-select").append(option); - } - $("#create-keys").modal(); - }); -}); - -$('#create-keys-select').change(function(){ - var key_type_name = $(this).find("option:selected").text(); - - $.get(script_root + '/static/admin/js/templates/keys/'+key_type_name +'/'+key_type_name+'.hbs', function(template_data){ - var template = Handlebars.compile(template_data); - $("#create-keys-entry-div").html(template()); - $("#create-keys-button-div").show(); - }); -}); - - -$('#create-keys-submit').click(function (e) { - e.preventDefault(); - var chalid = $('#create-keys').find('.chal-id').val(); - var key_data = $('#create-keys').find('input[name=key]').val(); - var key_type = $('#create-keys-select').val(); - create_key(chalid, key_data, key_type); -}); - - -$('#create-hint').click(function(e){ - e.preventDefault(); - load_hint_modal('create'); -}); - -$('#hint-modal-submit').submit(function (e) { - e.preventDefault(); - var params = {} - $(this).serializeArray().map(function(x){ - params[x.name] = x.value; - }); - $.post(script_root + $(this).attr('action'), params, function(data){ - loadhints(params['chal']); - }); - $("#hint-modal").modal('hide'); -}); - - $(function(){ loadchals(); }) diff --git a/CTFd/static/admin/js/multi-modal.js b/CTFd/static/admin/js/multi-modal.js index 37dd3b2b..0c4781d0 100644 --- a/CTFd/static/admin/js/multi-modal.js +++ b/CTFd/static/admin/js/multi-modal.js @@ -3,7 +3,6 @@ var MultiModal = function(element) { this.$element = $(element); - this.modalCount = 0; }; MultiModal.BASE_ZINDEX = 1040; @@ -11,30 +10,32 @@ MultiModal.prototype.show = function(target) { var that = this; var $target = $(target); - var modalIndex = that.modalCount++; + var modalCount = $('.modal:visible').length; - $target.css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20) + 10); + $target.css('z-index', MultiModal.BASE_ZINDEX + (modalCount * 20) + 10); window.setTimeout(function() { - if(modalIndex > 0) + var modalCount = $('.modal:visible').length; + if(modalCount > 0) $('.modal-backdrop').not(':first').addClass('hidden'); - that.adjustBackdrop(); + that.adjustBackdrop(modalCount); }); }; MultiModal.prototype.hidden = function(target) { - this.modalCount--; + var modalCount = $('.modal:visible').length; - if(this.modalCount) { - this.adjustBackdrop(); + var $target = $(target); + + if(modalCount) { + this.adjustBackdrop(modalCount - 1); $('body').addClass('modal-open'); } }; - MultiModal.prototype.adjustBackdrop = function() { - var modalIndex = this.modalCount - 1; - $('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20)); + MultiModal.prototype.adjustBackdrop = function(modalCount) { + $('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + ((modalCount)* 20)); }; function Plugin(method, target) { diff --git a/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-modals.hbs b/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-modals.hbs new file mode 100644 index 00000000..09ccb2f8 --- /dev/null +++ b/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-modals.hbs @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-update.hbs b/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-update.hbs new file mode 100644 index 00000000..e69de29b diff --git a/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-update.js b/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-update.js new file mode 100644 index 00000000..650d409e --- /dev/null +++ b/CTFd/static/admin/js/templates/challenges/standard/standard-challenge-update.js @@ -0,0 +1,390 @@ +//http://stackoverflow.com/a/2648463 - wizardry! +String.prototype.format = String.prototype.f = function() { + var s = this, + i = arguments.length; + + while (i--) { + s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]); + } + return s; +}; + +function load_hint_modal(method, hintid){ + $('#hint-modal-hint').val(''); + $('#hint-modal-cost').val(''); + if (method == 'create'){ + $('#hint-modal-submit').attr('action', '/admin/hints'); + $('#hint-modal-title').text('Create Hint'); + $("#hint-modal").modal(); + } else if (method == 'update'){ + $.get(script_root + '/admin/hints/' + hintid, function(data){ + $('#hint-modal-submit').attr('action', '/admin/hints/' + hintid); + $('#hint-modal-hint').val(data.hint); + $('#hint-modal-cost').val(data.cost); + $('#hint-modal-title').text('Update Hint'); + $("#hint-modal-button").text('Update Hint'); + $("#hint-modal").modal(); + }); + } +} + +function submitkey(chal, key) { + $.post(script_root + "/admin/chal/" + chal, { + key: key, + nonce: $('#nonce').val() + }, function (data) { + alert(data) + }) +} + +function create_key(chal, key, key_type) { + $.post(script_root + "/admin/keys", { + chal: chal, + key: key, + key_type: key_type, + nonce: $('#nonce').val() + }, function (data) { + if (data == "1"){ + loadkeys(chal); + $("#create-keys").modal('toggle'); + } + }); +} + +function loadkeys(chal){ + $.get(script_root + '/admin/chal/' + chal + '/keys', function(data){ + $('#keys-chal').val(chal); + keys = $.parseJSON(JSON.stringify(data)); + keys = keys['keys']; + $('#current-keys').empty(); + $.get(script_root + "/static/admin/js/templates/admin-keys-table.hbs", function(data){ + var template = Handlebars.compile(data); + var wrapper = {keys: keys, script_root: script_root}; + $('#current-keys').append(template(wrapper)); + }); + }); +} + +function updatekeys(){ + keys = []; + vals = []; + chal = $('#keys-chal').val() + $('.current-key').each(function(){ + keys.push($(this).val()); + }) + $('#current-keys input[name*="key_type"]:checked').each(function(){ + vals.push($(this).val()); + }) + $.post(script_root + '/admin/keys/'+chal, {'keys':keys, 'vals':vals, 'nonce': $('#nonce').val()}) + loadchal(chal, true) + $('#update-keys').modal('hide'); +} + + +function deletekey(key_id){ + $.post(script_root + '/admin/keys/'+key_id+'/delete', {'nonce': $('#nonce').val()}, function(data){ + if (data == "1") { + $('tr[name={0}]'.format(key_id)).remove(); + } + }); +} + +function updatekey(){ + var key_id = $('#key-id').val(); + var chal = $('#keys-chal').val(); + var key_data = $('#key-data').val(); + var key_type = $('#key-type').val(); + var nonce = $('#nonce').val(); + $.post(script_root + '/admin/keys/'+key_id, { + 'chal':chal, + 'key':key_data, + 'key_type': key_type, + 'nonce': nonce + }, function(data){ + if (data == "1") { + loadkeys(chal); + $('#edit-keys').modal('toggle'); + } + }) +} + +function loadtags(chal){ + $('#tags-chal').val(chal) + $('#current-tags').empty() + $('#chal-tags').empty() + $.get(script_root + '/admin/tags/'+chal, function(data){ + tags = $.parseJSON(JSON.stringify(data)) + tags = tags['tags'] + for (var i = 0; i < tags.length; i++) { + tag = ""+tags[i].tag+"×" + $('#current-tags').append(tag) + }; + $('.delete-tag').click(function(e){ + deletetag(e.target.name) + $(e.target).parent().remove() + }); + }); +} + +function deletetag(tagid){ + $.post(script_root + '/admin/tags/'+tagid+'/delete', {'nonce': $('#nonce').val()}); +} + + +function edithint(hintid){ + $.get(script_root + '/admin/hints/' + hintid, function(data){ + console.log(data); + }) +} + + +function deletehint(hintid){ + $.delete(script_root + '/admin/hints/' + hintid, function(data, textStatus, jqXHR){ + if (jqXHR.status == 204){ + var chalid = $('.chal-id').val(); + loadhints(chalid); + } + }); +} + + +function loadhints(chal){ + $.get(script_root + '/admin/chal/{0}/hints'.format(chal), function(data){ + var table = $('#hintsboard > tbody'); + table.empty(); + for (var i = 0; i < data.hints.length; i++) { + var hint = data.hints[i] + var hint_row = "" + + "{0}".format(hint.hint) + + "{0}".format(hint.cost) + + "" + + "".format(hint.id)+ + "".format(hint.id)+ + "" + + ""; + table.append(hint_row); + } + }); +} + + +function deletechal(chalid){ + $.post(script_root + '/admin/chal/delete', {'nonce':$('#nonce').val(), 'id':chalid}); +} + +function updatetags(){ + tags = []; + chal = $('#tags-chal').val() + $('#chal-tags > span > span').each(function(i, e){ + tags.push($(e).text()) + }); + $.post(script_root + '/admin/tags/'+chal, {'tags':tags, 'nonce': $('#nonce').val()}) + loadchal(chal) +} + +function updatefiles(){ + chal = $('#files-chal').val(); + var form = $('#update-files form')[0]; + var formData = new FormData(form); + $.ajax({ + url: script_root + '/admin/files/'+chal, + data: formData, + type: 'POST', + cache: false, + contentType: false, + processData: false, + success: function(data){ + form.reset(); + loadfiles(chal); + $('#update-files').modal('hide'); + } + }); +} + +function loadfiles(chal){ + $('#update-files form').attr('action', script_root+'/admin/files/'+chal) + $.get(script_root + '/admin/files/' + chal, function(data){ + $('#files-chal').val(chal) + files = $.parseJSON(JSON.stringify(data)); + files = files['files'] + $('#current-files').empty() + for(x=0; x'+''+filename+'Delete') + } + }); +} + +function deletefile(chal, file, elem){ + $.post(script_root + '/admin/files/' + chal,{ + 'nonce': $('#nonce').val(), + 'method': 'delete', + 'file': file + }, function (data){ + if (data == "1") { + elem.parent().remove() + } + }); +} + +$('#submit-key').click(function (e) { + submitkey($('#chalid').val(), $('#answer').val()) +}); + +$('#submit-keys').click(function (e) { + e.preventDefault(); + $('#update-keys').modal('hide'); +}); + +$('#submit-tags').click(function (e) { + e.preventDefault(); + updatetags() +}); + +$('#submit-files').click(function (e) { + e.preventDefault(); + updatefiles() +}); + +$('#delete-chal form').submit(function(e){ + e.preventDefault(); + $.post(script_root + '/admin/chal/delete', $(this).serialize(), function(data){ + console.log(data) + if (data){ + loadchals(); + } + else { + alert('There was an error'); + } + }) + $("#delete-chal").modal("hide"); + $("#update-challenge").modal("hide"); +}); + +$(".tag-insert").keyup(function (e) { + if (e.keyCode == 13) { + tag = $('.tag-insert').val() + tag = tag.replace(/'/g, ''); + if (tag.length > 0){ + tag = ""+tag+"×" + $('#chal-tags').append(tag) + } + $('.tag-insert').val("") + } +}); + +$('#limit_max_attempts').change(function() { + if(this.checked) { + $('#chal-attempts-group').show(); + } else { + $('#chal-attempts-group').hide(); + $('#chal-attempts-input').val(''); + } +}); + +// Markdown Preview +$('#desc-edit').on('shown.bs.tab', function (event) { + if (event.target.hash == '#desc-preview'){ + $(event.target.hash).html(marked($('#desc-editor').val(), {'gfm':true, 'breaks':true})) + } +}); +$('#new-desc-edit').on('shown.bs.tab', function (event) { + if (event.target.hash == '#new-desc-preview'){ + $(event.target.hash).html(marked($('#new-desc-editor').val(), {'gfm':true, 'breaks':true})) + } +}); + +// Open New Challenge modal when New Challenge button is clicked +// $('.create-challenge').click(function (e) { +// $('#create-challenge').modal(); +// }); + + +$('#create-key').click(function(e){ + $.get(script_root + '/admin/key_types', function(data){ + $("#create-keys-select").empty(); + var option = ""; + $("#create-keys-select").append(option); + for (var key in data){ + var option = "".format(key, data[key]); + $("#create-keys-select").append(option); + } + $("#create-keys").modal(); + }); +}); + +$('#create-keys-select').change(function(){ + var key_type_name = $(this).find("option:selected").text(); + + $.get(script_root + '/static/admin/js/templates/keys/'+key_type_name +'/'+key_type_name+'.hbs', function(template_data){ + var template = Handlebars.compile(template_data); + $("#create-keys-entry-div").html(template()); + $("#create-keys-button-div").show(); + }); +}); + + +$('#create-keys-submit').click(function (e) { + e.preventDefault(); + var chalid = $('#create-keys').find('.chal-id').val(); + var key_data = $('#create-keys').find('input[name=key]').val(); + var key_type = $('#create-keys-select').val(); + create_key(chalid, key_data, key_type); +}); + + +$('#create-hint').click(function(e){ + e.preventDefault(); + load_hint_modal('create'); +}); + +$('#hint-modal-submit').submit(function (e) { + e.preventDefault(); + var params = {} + $(this).serializeArray().map(function(x){ + params[x.name] = x.value; + }); + $.post(script_root + $(this).attr('action'), params, function(data){ + loadhints(params['chal']); + }); + $("#hint-modal").modal('hide'); +}); + +function loadchal(id, update) { + // $('#chal *').show() + // $('#chal > h1').hide() + obj = $.grep(challenges['game'], function (e) { + return e.id == id; + })[0] + $('#desc-write-link').click() // Switch to Write tab + $('.chal-title').text(obj.name); + $('.chal-name').val(obj.name); + $('.chal-desc').val(obj.description); + $('.chal-value').val(obj.value); + if (parseInt(obj.max_attempts) > 0){ + $('.chal-attempts').val(obj.max_attempts); + $('#limit_max_attempts').prop('checked', true); + $('#chal-attempts-group').show(); + } + $('.chal-category').val(obj.category); + $('.chal-id').val(obj.id); + $('.chal-hidden').prop('checked', false); + if (obj.hidden) { + $('.chal-hidden').prop('checked', true); + } + //$('#update-challenge .chal-delete').attr({ + // 'href': '/admin/chal/close/' + (id + 1) + //}) + if (typeof update === 'undefined') + $('#update-challenge').modal(); +} + +function openchal(id){ + loadchal(id); + loadkeys(id); + loadhints(id); + loadtags(id); + loadfiles(id); +} + diff --git a/CTFd/static/admin/js/utils.js b/CTFd/static/admin/js/utils.js index 1dc99fba..bb47551f 100644 --- a/CTFd/static/admin/js/utils.js +++ b/CTFd/static/admin/js/utils.js @@ -79,4 +79,4 @@ jQuery.each(["put", "delete"], function(i, method) { success: callback }); }; -}); \ No newline at end of file +}); diff --git a/CTFd/templates/admin/chals.html b/CTFd/templates/admin/chals.html index 1f5028ee..45408f1f 100644 --- a/CTFd/templates/admin/chals.html +++ b/CTFd/templates/admin/chals.html @@ -31,338 +31,11 @@

New Challenge

- - - - - - - - - - - - - - - - - - -