mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 14:04:20 +01:00
Simplify url_for calls in themes, rework CTFd.js, fix flaky test (#826)
* Simplify url_for calls in themes, rework CTFd.js, fix flaky test
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/jumbotron.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/sticky-footer.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/base.css') }}">
|
||||
<script src="{{ url_for('views.themes', theme='core', path='js/CTFd.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme='admin', path='js/vendor/promise-polyfill.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme='admin', path='js/vendor/fetch.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme='admin', path='js/vendor/moment.min.js') }}"></script>
|
||||
@@ -23,6 +24,8 @@
|
||||
var script_root = "{{ request.script_root }}";
|
||||
var csrf_nonce = "{{ nonce }}";
|
||||
var user_mode = "{{ get_config('user_mode') }}";
|
||||
CTFd.options.urlRoot = script_root;
|
||||
CTFd.options.csrfNonce = csrf_nonce;
|
||||
</script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
{% for stylesheet in get_registered_admin_stylesheets() %}
|
||||
|
||||
@@ -1,173 +1,34 @@
|
||||
var CTFd = (function () {
|
||||
|
||||
var urlRoot = '';
|
||||
|
||||
var challenges = {
|
||||
all: function(){
|
||||
return fetch(urlRoot + '/api/v1/challenges', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
get: function(challengeId){
|
||||
return fetch(urlRoot + '/api/v1/challenges/' + challengeId, {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
data.solves = function () {
|
||||
return fetch(urlRoot + '/api/v1/challenges/' + this.id + '/solves', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
var options = {
|
||||
urlRoot: '',
|
||||
csrfNonce: '',
|
||||
};
|
||||
|
||||
var challenges = {};
|
||||
|
||||
var scoreboard = function() {};
|
||||
|
||||
var teams = {};
|
||||
|
||||
var users = {};
|
||||
|
||||
var fetch = function(url, options) {
|
||||
if (options === undefined) {
|
||||
options = {
|
||||
method: "GET",
|
||||
credentials: "same-origin",
|
||||
headers: {},
|
||||
};
|
||||
return data;
|
||||
});
|
||||
},
|
||||
types: function(){
|
||||
return fetch(urlRoot + '/api/v1/challenges/types', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
solves: function () {
|
||||
return fetch(urlRoot + '/api/v1/statistics/challenges/solves', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
}
|
||||
};
|
||||
url = this.options.urlRoot + url;
|
||||
|
||||
var scoreboard = function() {
|
||||
return fetch(urlRoot + '/api/v1/scoreboard', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
options.credentials = 'same-origin';
|
||||
options.headers['Accept'] = 'application/json';
|
||||
options.headers['Content-Type'] = 'application/json';
|
||||
options.headers['CSRF-Token'] = this.options.csrfNonce;
|
||||
|
||||
var teams = {
|
||||
all: function () {
|
||||
return fetch(urlRoot + '/api/v1/teams', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
get: function (teamId) {
|
||||
return fetch(urlRoot + '/api/v1/teams/' + teamId, {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
data.solves = function () {
|
||||
|
||||
};
|
||||
data.fails = function () {
|
||||
|
||||
};
|
||||
data.awards = function () {
|
||||
|
||||
};
|
||||
return data;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
var users = {
|
||||
all: function () {
|
||||
return fetch(urlRoot + '/api/v1/users', {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
get: function (userId) {
|
||||
return fetch(urlRoot + '/api/v1/users/' + userId, {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
data.solves = function () {
|
||||
|
||||
};
|
||||
data.fails = function () {
|
||||
|
||||
};
|
||||
data.awards = function () {
|
||||
|
||||
};
|
||||
return data;
|
||||
});
|
||||
},
|
||||
return window.fetch(url, options);
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -175,5 +36,7 @@ var CTFd = (function () {
|
||||
scoreboard: scoreboard,
|
||||
teams: teams,
|
||||
users: users,
|
||||
fetch: fetch,
|
||||
options: options
|
||||
};
|
||||
})();
|
||||
@@ -4,15 +4,15 @@
|
||||
<title>{{ get_ctf_name() }}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='img/favicon.ico') }}"
|
||||
<link rel="shortcut icon" href="{{ url_for('views.themes', path='img/favicon.ico') }}"
|
||||
type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/vendor/bootstrap.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/vendor/font-awesome/fontawesome-fonts.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/vendor/font-awesome/fontawesome-all.min.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/vendor/font.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/jumbotron.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/sticky-footer.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/base.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/vendor/bootstrap.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/vendor/font-awesome/fontawesome-fonts.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/vendor/font-awesome/fontawesome-all.min.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/vendor/font.css') }}" type='text/css'>
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/jumbotron.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/sticky-footer.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/base.css') }}">
|
||||
{% block stylesheets %}{% endblock %}
|
||||
{% for stylesheet in get_registered_stylesheets() %}
|
||||
{% if stylesheet.startswith('http') %}
|
||||
@@ -24,17 +24,18 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('views.custom_css') }}">
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/promise-polyfill.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/fetch.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/CTFd.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/moment.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/nunjucks.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/socket.io.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/promise-polyfill.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/fetch.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/CTFd.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/moment.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/nunjucks.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/socket.io.min.js') }}"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
var csrf_nonce = "{{ nonce }}";
|
||||
var user_mode = "{{ get_config('user_mode') }}";
|
||||
CTFd.urlRoot = script_root;
|
||||
CTFd.options.urlRoot = script_root;
|
||||
CTFd.options.csrfNonce = csrf_nonce;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -142,13 +143,13 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/jquery.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/markdown-it.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/bootstrap.bundle.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/ezq.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/events.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/jquery.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/markdown-it.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/bootstrap.bundle.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/ezq.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/events.js') }}"></script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme=get_ctf_theme(), path='css/challenge-board.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', path='css/challenge-board.css') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -56,11 +56,11 @@
|
||||
<script>
|
||||
var authed = {{ (id is defined) | tojson }};
|
||||
</script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/multi-modal.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/multi-modal.js') }}"></script>
|
||||
{% if admin or not errors %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/challenges.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/hints.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/challenges.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/hints.js') }}"></script>
|
||||
{% endif %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -59,6 +59,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -54,5 +54,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/scoreboard.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/scoreboard.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -93,6 +93,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/settings.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/settings.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -87,5 +87,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/style.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/style.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -158,9 +158,9 @@
|
||||
{% endif %}
|
||||
var team_account_id = team_self ? "me" : team_id;
|
||||
</script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
{% if solves %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/team.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/team.js') }}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
{% if solves %}
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/team.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/team.js') }}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
var user_self = {{ (user.id == id) | tojson }};
|
||||
var user_account_id = user_self ? "me" : user_id;
|
||||
</script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/user.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/vendor/plotly.min.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/utils.js') }}"></script>
|
||||
<script src="{{ url_for('views.themes', path='js/user.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -71,6 +71,11 @@ def init_request_processors(app):
|
||||
return dict(session)
|
||||
return dict()
|
||||
|
||||
@app.url_defaults
|
||||
def inject_theme(endpoint, values):
|
||||
if 'theme' not in values and app.url_map.is_endpoint_expecting(endpoint, 'theme'):
|
||||
values['theme'] = ctf_theme()
|
||||
|
||||
@app.before_request
|
||||
def needs_setup():
|
||||
if request.path == url_for('views.setup') or request.path.startswith('/themes'):
|
||||
|
||||
@@ -107,12 +107,12 @@ def test_api_hint_admin_access():
|
||||
admin = login_as_user(app, "admin")
|
||||
register_user(app)
|
||||
client = login_as_user(app)
|
||||
r = client.patch('/api/v1/hints/1')
|
||||
assert r.status_code == 302
|
||||
r = client.delete('/api/v1/hints/1')
|
||||
assert r.status_code == 302
|
||||
r = client.patch('/api/v1/hints/1', json="")
|
||||
assert r.status_code == 403
|
||||
r = client.delete('/api/v1/hints/1', json="")
|
||||
assert r.status_code == 403
|
||||
r_admin = admin.patch('/api/v1/hints/1', json={"cost": 2})
|
||||
assert r_admin.status_code == 200
|
||||
r_admin = admin.delete('/api/v1/hints/1')
|
||||
r_admin = admin.delete('/api/v1/hints/1', json="")
|
||||
assert r_admin.status_code == 200
|
||||
destroy_ctfd(app)
|
||||
|
||||
Reference in New Issue
Block a user