mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-18 22:44:24 +01:00
Allowing for deletion of solves and wrong keys
This commit is contained in:
@@ -485,6 +485,15 @@ def delete_solve(teamid, chalid):
|
|||||||
return '1'
|
return '1'
|
||||||
|
|
||||||
|
|
||||||
|
@admin.route('/admin/wrong_keys/<teamid>/<chalid>/delete', methods=['POST'])
|
||||||
|
@admins_only
|
||||||
|
def delete_wrong_key(teamid, chalid):
|
||||||
|
wrong_key = WrongKeys.query.filter_by(team=teamid, chalid=chalid).first()
|
||||||
|
db.session.delete(wrong_key)
|
||||||
|
db.session.commit()
|
||||||
|
return '1'
|
||||||
|
|
||||||
|
|
||||||
@admin.route('/admin/statistics', methods=['GET'])
|
@admin.route('/admin/statistics', methods=['GET'])
|
||||||
@admins_only
|
@admins_only
|
||||||
def admin_stats():
|
def admin_stats():
|
||||||
@@ -516,7 +525,7 @@ def admin_wrong_key(page='1'):
|
|||||||
page_start = results_per_page * ( page - 1 )
|
page_start = results_per_page * ( page - 1 )
|
||||||
page_end = results_per_page * ( page - 1 ) + results_per_page
|
page_end = results_per_page * ( page - 1 ) + results_per_page
|
||||||
|
|
||||||
wrong_keys = WrongKeys.query.add_columns(WrongKeys.flag, WrongKeys.team, WrongKeys.date,\
|
wrong_keys = WrongKeys.query.add_columns(WrongKeys.chalid, WrongKeys.flag, WrongKeys.team, WrongKeys.date,\
|
||||||
Challenges.name.label('chal_name'), Teams.name.label('team_name')).\
|
Challenges.name.label('chal_name'), Teams.name.label('team_name')).\
|
||||||
join(Challenges).join(Teams).order_by('team_name ASC').slice(page_start, page_end).all()
|
join(Challenges).join(Teams).order_by('team_name ASC').slice(page_start, page_end).all()
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<h3>Delete Key</h3>
|
<h3>Delete Key</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form method="POST" action="/admin/chal/delete">
|
<form method="POST" action="">
|
||||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||||
<div class="small-6 small-centered text-center columns">
|
<div class="small-6 small-centered text-center columns">
|
||||||
<p>Are you sure you want to delete successful key submission for team: <strong id="confirm-team-name"></strong> in challenge: <strong id="confirm-chal-name"></strong>?</p>
|
<p>Are you sure you want to delete successful key submission for team: <strong id="confirm-team-name"></strong> in challenge: <strong id="confirm-chal-name"></strong>?</p>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table id="teamsboard">
|
<table id="teamsboard" class=" table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center"><b>Team</b>
|
<td class="text-center"><b>Team</b>
|
||||||
@@ -50,10 +50,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="text-center team" id="{{ solve.teamid }}"><a href="/admin/team/{{ solve.teamid }}">{{ solve.team_name }}</a>
|
<td class="text-center team" id="{{ solve.teamid }}"><a href="/admin/team/{{ solve.teamid }}">{{ solve.team_name }}</a>
|
||||||
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal_name }}</td>
|
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal_name }}</td>
|
||||||
<td class="text-center">{{ solve.date }}</td>
|
<td class="text-center solve-time">{{ solve.date|unix_time_millis }}</td>
|
||||||
<td class="text-center">{{ solve.flag }}</td>
|
<td class="text-center">{{ solve.flag }}</td>
|
||||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -71,33 +70,37 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||||
$('#delete-solve').click(function(e){
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
|
||||||
e.preventDefault();
|
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.js"></script>
|
||||||
var solve = $('#confirm input[name="solve"]').val()
|
<script src="/static/admin/js/team.js"></script>
|
||||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
<script>
|
||||||
var data = $.parseJSON(JSON.stringify(data))
|
$('#delete-solve').click(function(e){
|
||||||
if (data == "1"){
|
e.preventDefault();
|
||||||
location.reload()
|
var solve = $('#confirm input[name="solve"]').val()
|
||||||
}
|
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||||
})
|
var data = $.parseJSON(JSON.stringify(data))
|
||||||
});
|
if (data == "1"){
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
function load_confirm_modal(team, chal, team_name, chal_name){
|
function load_confirm_modal(team, chal, team_name, chal_name){
|
||||||
var modal = $('#confirm')
|
var modal = $('#confirm')
|
||||||
modal.find('#confirm-team-name').text(team_name)
|
modal.find('#confirm-team-name').text(team_name)
|
||||||
modal.find('#confirm-chal-name').text(chal_name)
|
modal.find('#confirm-chal-name').text(chal_name)
|
||||||
$('#confirm form').attr('action', '/admin/solves/'+team+'/'+chal+'/delete');
|
$('#confirm form').attr('action', '/admin/solves/'+team+'/'+chal+'/delete');
|
||||||
$('#confirm').modal('show');
|
$('#confirm').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.fa-times').click(function(){
|
$('.fa-times').click(function(){
|
||||||
var elem = $(this).parent().parent();
|
var elem = $(this).parent().parent();
|
||||||
var chal = elem.find('.chal').attr('id');
|
var chal = elem.find('.chal').attr('id');
|
||||||
var chal_name = elem.find('.chal').text().trim();
|
var chal_name = elem.find('.chal').text().trim();
|
||||||
var team = elem.find('.team').attr('id');
|
var team = elem.find('.team').attr('id');
|
||||||
var team_name = elem.find('.team').text().trim();
|
var team_name = elem.find('.team').text().trim();
|
||||||
load_confirm_modal(team, chal, team_name, chal_name)
|
load_confirm_modal(team, chal, team_name, chal_name)
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,9 +1,44 @@
|
|||||||
{% extends "admin/base.html" %}
|
{% extends "admin/base.html" %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
<style>
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #337ab7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background-color: #d9534f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
|
<div id="confirm" class="modal fade" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header text-center">
|
||||||
|
<h3>Delete Key</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form method="POST" action="/admin/chal/delete">
|
||||||
|
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||||
|
<div class="small-6 small-centered text-center columns">
|
||||||
|
<p>Are you sure you want to delete <strong class="key-type">successful</strong> key submission for team: <strong
|
||||||
|
id="confirm-team-name"></strong> in challenge: <strong
|
||||||
|
id="confirm-chal-name"></strong>?</p>
|
||||||
|
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||||
|
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1 id="team-id">{{ team.name }}</h1>
|
<h1 id="team-id">{{ team.name }}</h1>
|
||||||
<h2 id="team-email" class="text-center">{{ team.email }}</h2>
|
<h2 id="team-email" class="text-center">{{ team.email }}</h2>
|
||||||
<h2 id="team-place" class="text-center">
|
<h2 id="team-place" class="text-center">
|
||||||
@@ -23,40 +58,45 @@
|
|||||||
<div id="score-graph"></div>
|
<div id="score-graph"></div>
|
||||||
|
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<h3>Solves</h3>
|
<h3>IP Addresses</h3>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Challenge</b></td>
|
<td class="text-center"><b>IP Address</b></td>
|
||||||
<td><b>Submitted</b></td>
|
<td class="text-center"><b>Last Seen</b></td>
|
||||||
<td><b>Category</b></td>
|
</tr>
|
||||||
<td><b>Value</b></td>
|
|
||||||
<td><b>Time</b></td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for solve in solves %}
|
{% for addr in addrs %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ solve.chal.name }}</td>
|
<td class="text-center">{{ addr.ip|long2ip }}</td>
|
||||||
<td>{{ solve.flag }}</td>
|
<td class="text-center solve-time">{{ addr.date|unix_time_millis }}</td>
|
||||||
<td>{{ solve.chal.category }}</td>
|
|
||||||
<td>{{ solve.chal.value }}</td>
|
|
||||||
<td class="solve-time">{{ solve.date|unix_time_millis }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<h3>IP Addresses</h3>
|
<h3>Solves</h3>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>IP Address</b></td>
|
<td class="text-center"><b>Challenge</b></td>
|
||||||
<td><b>Last Seen</b></td>
|
<td class="text-center"><b>Submitted</b></td>
|
||||||
|
<td class="text-center"><b>Category</b></td>
|
||||||
|
<td class="text-center"><b>Value</b></td>
|
||||||
|
<td class="text-center"><b>Time</b></td>
|
||||||
|
<td class="text-center"><b>Delete</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for addr in addrs %}
|
{% for solve in solves %}
|
||||||
<tr><td>{{ addr.ip|long2ip }}</td><td class="solve-time">{{ addr.date|unix_time_millis }}</td></tr>
|
<tr class="chal-solve">
|
||||||
|
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal.name }}</td>
|
||||||
|
<td class="text-center">{{ solve.flag }}</td>
|
||||||
|
<td class="text-center">{{ solve.chal.category }}</td>
|
||||||
|
<td class="text-center">{{ solve.chal.value }}</td>
|
||||||
|
<td class="text-center solve-time">{{ solve.date|unix_time_millis }}</td>
|
||||||
|
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -65,17 +105,19 @@
|
|||||||
<h3>Wrong Keys</h3>
|
<h3>Wrong Keys</h3>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Challenge</b></td>
|
<td class="text-center"><b>Challenge</b></td>
|
||||||
<td><b>Submitted</b></td>
|
<td class="text-center"><b>Submitted</b></td>
|
||||||
<td><b>Time</b></td>
|
<td class="text-center"><b>Time</b></td>
|
||||||
|
<td class="text-center"><b>Delete</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for wrong_key in wrong_keys %}
|
{% for wrong_key in wrong_keys %}
|
||||||
<tr>
|
<tr class="chal-wrong">
|
||||||
<td>{{ wrong_key.chal.name }}</td>
|
<td class="text-center chal" id="{{ wrong_key.chalid }}">{{ wrong_key.chal.name }}</td>
|
||||||
<td>{{ wrong_key.flag }}</td>
|
<td class="text-center">{{ wrong_key.flag }}</td>
|
||||||
<td class="solve-time">{{ wrong_key.date|unix_time_millis }}</td>
|
<td class="text-center solve-time">{{ wrong_key.date|unix_time_millis }}</td>
|
||||||
|
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -90,4 +132,41 @@
|
|||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.js"></script>
|
||||||
<script src="/static/admin/js/team.js"></script>
|
<script src="/static/admin/js/team.js"></script>
|
||||||
|
<script>
|
||||||
|
$('#delete-solve').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var solve = $('#confirm input[name="solve"]').val()
|
||||||
|
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function (data) {
|
||||||
|
var data = $.parseJSON(JSON.stringify(data))
|
||||||
|
if (data == "1") {
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function load_confirm_modal(type, team, chal, team_name, chal_name) {
|
||||||
|
var modal = $('#confirm')
|
||||||
|
modal.find('#confirm-team-name').text(team_name);
|
||||||
|
modal.find('#confirm-chal-name').text(chal_name);
|
||||||
|
if (type == 'chal-solve'){
|
||||||
|
$('.key-type').text('correct');
|
||||||
|
$('#confirm form').attr('action', '/admin/solves/' + team + '/' + chal + '/delete');
|
||||||
|
} else {
|
||||||
|
$('.key-type').text('incorrect');
|
||||||
|
$('#confirm form').attr('action', '/admin/wrong_keys/' + team + '/' + chal + '/delete');
|
||||||
|
}
|
||||||
|
$('#confirm').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.fa-times').click(function () {
|
||||||
|
|
||||||
|
var elem = $(this).parent().parent();
|
||||||
|
var type = elem.attr('class');
|
||||||
|
var chal = elem.find('.chal').attr('id');
|
||||||
|
var chal_name = elem.find('.chal').text().trim();
|
||||||
|
var team = window.location.pathname.split('/').pop();
|
||||||
|
var team_name = $("#team-id").text();
|
||||||
|
load_confirm_modal(type, team, chal, team_name, chal_name)
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,10 +1,43 @@
|
|||||||
{% extends "admin/base.html" %}
|
{% extends "admin/base.html" %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
<style>
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #337ab7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background-color: #d9534f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h1>Incorrect Key Submissions</h1>
|
<h1>Incorrect Key Submissions</h1>
|
||||||
<table id="teamsboard">
|
<div id="confirm" class="modal fade" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header text-center">
|
||||||
|
<h3>Delete Key</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form method="POST" action="">
|
||||||
|
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||||
|
<div class="small-6 small-centered text-center columns">
|
||||||
|
<p>Are you sure you want to delete incorrect key submission for team: <strong
|
||||||
|
id="confirm-team-name"></strong> in challenge: <strong
|
||||||
|
id="confirm-chal-name"></strong>?</p>
|
||||||
|
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||||
|
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table id="teamsboard" class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center"><b>Team</b>
|
<td class="text-center"><b>Team</b>
|
||||||
@@ -15,16 +48,18 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-center"><b>Submitted Key</b>
|
<td class="text-center"><b>Submitted Key</b>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="text-center"><b>Delete</b>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for wrong_key in wrong_keys %}
|
{% for wrong_key in wrong_keys %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center"><a href="/admin/team/{{ wrong_key.team }}">{{ wrong_key.team_name }}</a>
|
<td class="text-center team" id="{{ wrong_key.team }}"><a href="/admin/team/{{ wrong_key.team }}">{{ wrong_key.team_name }}</a>
|
||||||
<td class="text-center">{{ wrong_key.chal_name }}</td>
|
<td class="text-center chal" id="{{ wrong_key.chalid }}">{{ wrong_key.chal_name }}</td>
|
||||||
<td class="text-center">{{ wrong_key.date }}</td>
|
<td class="text-center solve-time">{{ wrong_key.date|unix_time_millis }}</td>
|
||||||
<td class="text-center">{{ wrong_key.flag }}</td>
|
<td class="text-center">{{ wrong_key.flag }}</td>
|
||||||
</td>
|
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -42,4 +77,37 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.js"></script>
|
||||||
|
<script src="/static/admin/js/team.js"></script>
|
||||||
|
<script>
|
||||||
|
$('#delete-solve').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var solve = $('#confirm input[name="solve"]').val();
|
||||||
|
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function (data) {
|
||||||
|
var data = $.parseJSON(JSON.stringify(data));
|
||||||
|
if (data == "1") {
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function load_confirm_modal(team, chal, team_name, chal_name) {
|
||||||
|
var modal = $('#confirm')
|
||||||
|
modal.find('#confirm-team-name').text(team_name);
|
||||||
|
modal.find('#confirm-chal-name').text(chal_name);
|
||||||
|
$('#confirm form').attr('action', '/admin/wrong_keys/' + team + '/' + chal + '/delete');
|
||||||
|
$('#confirm').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.fa-times').click(function () {
|
||||||
|
var elem = $(this).parent().parent();
|
||||||
|
var chal = elem.find('.chal').attr('id');
|
||||||
|
var chal_name = elem.find('.chal').text().trim();
|
||||||
|
var team = elem.find('.team').attr('id');
|
||||||
|
var team_name = elem.find('.team').text().trim();
|
||||||
|
load_confirm_modal(team, chal, team_name, chal_name);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user