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:
Kevin Chung
2019-01-10 01:58:39 -05:00
committed by GitHub
parent 83e294057e
commit 9ee743de7e
15 changed files with 88 additions and 216 deletions

View File

@@ -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/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/sticky-footer.css') }}">
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/base.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/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/fetch.min.js') }}"></script>
<script src="{{ url_for('views.themes', theme='admin', path='js/vendor/moment.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 script_root = "{{ request.script_root }}";
var csrf_nonce = "{{ nonce }}"; var csrf_nonce = "{{ nonce }}";
var user_mode = "{{ get_config('user_mode') }}"; var user_mode = "{{ get_config('user_mode') }}";
CTFd.options.urlRoot = script_root;
CTFd.options.csrfNonce = csrf_nonce;
</script> </script>
{% block stylesheets %} {% endblock %} {% block stylesheets %} {% endblock %}
{% for stylesheet in get_registered_admin_stylesheets() %} {% for stylesheet in get_registered_admin_stylesheets() %}

View File

@@ -1,173 +1,34 @@
var CTFd = (function () { var CTFd = (function () {
var urlRoot = ''; var options = {
urlRoot: '',
csrfNonce: '',
};
var challenges = { var challenges = {};
all: function(){
return fetch(urlRoot + '/api/v1/challenges', { var scoreboard = function() {};
credentials: 'same-origin',
headers: { var teams = {};
'Accept': 'application/json',
'Content-Type': 'application/json' var users = {};
},
}) var fetch = function(url, options) {
.then(function (response) { if (options === undefined) {
return response.json(); options = {
}).then(function (data) { method: "GET",
return data; credentials: "same-origin",
}); headers: {},
}, };
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;
});
};
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() { options.credentials = 'same-origin';
return fetch(urlRoot + '/api/v1/scoreboard', { options.headers['Accept'] = 'application/json';
credentials: 'same-origin', options.headers['Content-Type'] = 'application/json';
headers: { options.headers['CSRF-Token'] = this.options.csrfNonce;
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
.then(function (response) {
return response.json();
}).then(function (data) {
return data;
});
};
var teams = { return window.fetch(url, options);
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 { return {
@@ -175,5 +36,7 @@ var CTFd = (function () {
scoreboard: scoreboard, scoreboard: scoreboard,
teams: teams, teams: teams,
users: users, users: users,
fetch: fetch,
options: options
}; };
})(); })();

View File

@@ -4,15 +4,15 @@
<title>{{ get_ctf_name() }}</title> <title>{{ get_ctf_name() }}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <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"> 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', 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', 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', 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', 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', 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', 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/base.css') }}">
{% block stylesheets %}{% endblock %} {% block stylesheets %}{% endblock %}
{% for stylesheet in get_registered_stylesheets() %} {% for stylesheet in get_registered_stylesheets() %}
{% if stylesheet.startswith('http') %} {% if stylesheet.startswith('http') %}
@@ -24,17 +24,18 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<link rel="stylesheet" type="text/css" href="{{ url_for('views.custom_css') }}"> <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', 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', 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', 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', 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', 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/socket.io.min.js') }}"></script>
<script type="text/javascript"> <script type="text/javascript">
var script_root = "{{ request.script_root }}"; var script_root = "{{ request.script_root }}";
var csrf_nonce = "{{ nonce }}"; var csrf_nonce = "{{ nonce }}";
var user_mode = "{{ get_config('user_mode') }}"; var user_mode = "{{ get_config('user_mode') }}";
CTFd.urlRoot = script_root; CTFd.options.urlRoot = script_root;
CTFd.options.csrfNonce = csrf_nonce;
</script> </script>
</head> </head>
<body> <body>
@@ -142,13 +143,13 @@
</div> </div>
</footer> </footer>
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/jquery.min.js') }}"></script> <script src="{{ url_for('views.themes', 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', 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', 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', 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', 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', 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/events.js') }}"></script>
{% block scripts %} {% block scripts %}
{% endblock %} {% endblock %}

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block stylesheets %} {% 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 %} {% endblock %}
{% block content %} {% block content %}
@@ -56,11 +56,11 @@
<script> <script>
var authed = {{ (id is defined) | tojson }}; var authed = {{ (id is defined) | tojson }};
</script> </script>
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/utils.js') }}"></script> <script src="{{ url_for('views.themes', 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/multi-modal.js') }}"></script>
{% if admin or not errors %} {% 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', 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/hints.js') }}"></script>
{% endif %} {% 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 %} {% endblock %}

View File

@@ -59,6 +59,6 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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 %} {% endblock %}

View File

@@ -22,6 +22,6 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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', 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/utils.js') }}"></script>
{% endblock %} {% endblock %}

View File

@@ -54,5 +54,5 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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 %} {% endblock %}

View File

@@ -75,7 +75,7 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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', 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/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/scoreboard.js') }}"></script>
{% endblock %} {% endblock %}

View File

@@ -93,6 +93,6 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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>
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/settings.js') }}"></script> <script src="{{ url_for('views.themes', path='js/settings.js') }}"></script>
{% endblock %} {% endblock %}

View File

@@ -87,5 +87,5 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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 %} {% endblock %}

View File

@@ -158,9 +158,9 @@
{% endif %} {% endif %}
var team_account_id = team_self ? "me" : team_id; var team_account_id = team_self ? "me" : team_id;
</script> </script>
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script> <script src="{{ url_for('views.themes', 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/utils.js') }}"></script>
{% if solves %} {% 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 %} {% endif %}
{% endblock %} {% endblock %}

View File

@@ -35,9 +35,9 @@
{% endblock %} {% endblock %}
{% block scripts %} {% 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', 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/utils.js') }}"></script>
{% if solves %} {% 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 %} {% endif %}
{% endblock %} {% endblock %}

View File

@@ -129,7 +129,7 @@
var user_self = {{ (user.id == id) | tojson }}; var user_self = {{ (user.id == id) | tojson }};
var user_account_id = user_self ? "me" : user_id; var user_account_id = user_self ? "me" : user_id;
</script> </script>
<script src="{{ url_for('views.themes', theme=get_ctf_theme(), path='js/vendor/plotly.min.js') }}"></script> <script src="{{ url_for('views.themes', 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/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/user.js') }}"></script>
{% endblock %} {% endblock %}

View File

@@ -71,6 +71,11 @@ def init_request_processors(app):
return dict(session) return dict(session)
return dict() 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 @app.before_request
def needs_setup(): def needs_setup():
if request.path == url_for('views.setup') or request.path.startswith('/themes'): if request.path == url_for('views.setup') or request.path.startswith('/themes'):

View File

@@ -107,12 +107,12 @@ def test_api_hint_admin_access():
admin = login_as_user(app, "admin") admin = login_as_user(app, "admin")
register_user(app) register_user(app)
client = login_as_user(app) client = login_as_user(app)
r = client.patch('/api/v1/hints/1') r = client.patch('/api/v1/hints/1', json="")
assert r.status_code == 302 assert r.status_code == 403
r = client.delete('/api/v1/hints/1') r = client.delete('/api/v1/hints/1', json="")
assert r.status_code == 302 assert r.status_code == 403
r_admin = admin.patch('/api/v1/hints/1', json={"cost": 2}) r_admin = admin.patch('/api/v1/hints/1', json={"cost": 2})
assert r_admin.status_code == 200 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 assert r_admin.status_code == 200
destroy_ctfd(app) destroy_ctfd(app)