From 9ee743de7e180133b7f85c12af934dea1969b3a5 Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Thu, 10 Jan 2019 01:58:39 -0500 Subject: [PATCH] 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 --- CTFd/themes/admin/templates/base.html | 3 + CTFd/themes/core/static/js/CTFd.js | 191 +++--------------- CTFd/themes/core/templates/base.html | 45 +++-- CTFd/themes/core/templates/challenges.html | 12 +- CTFd/themes/core/templates/confirm.html | 2 +- CTFd/themes/core/templates/notifications.html | 4 +- .../themes/core/templates/reset_password.html | 2 +- CTFd/themes/core/templates/scoreboard.html | 6 +- CTFd/themes/core/templates/settings.html | 4 +- CTFd/themes/core/templates/setup.html | 2 +- CTFd/themes/core/templates/teams/team.html | 6 +- .../core/templates/teams/team_enrollment.html | 6 +- CTFd/themes/core/templates/users/user.html | 6 +- CTFd/utils/initialization/__init__.py | 5 + tests/api/v1/user/test_hints.py | 10 +- 15 files changed, 88 insertions(+), 216 deletions(-) diff --git a/CTFd/themes/admin/templates/base.html b/CTFd/themes/admin/templates/base.html index 3c9e4211..add5bed1 100644 --- a/CTFd/themes/admin/templates/base.html +++ b/CTFd/themes/admin/templates/base.html @@ -14,6 +14,7 @@ + @@ -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; {% block stylesheets %} {% endblock %} {% for stylesheet in get_registered_admin_stylesheets() %} diff --git a/CTFd/themes/core/static/js/CTFd.js b/CTFd/themes/core/static/js/CTFd.js index 742e24eb..497c2f8f 100644 --- a/CTFd/themes/core/static/js/CTFd.js +++ b/CTFd/themes/core/static/js/CTFd.js @@ -1,173 +1,34 @@ var CTFd = (function () { - var urlRoot = ''; + var options = { + urlRoot: '', + csrfNonce: '', + }; - 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; - }); - }; - 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; - }); + var challenges = {}; + + var scoreboard = function() {}; + + var teams = {}; + + var users = {}; + + var fetch = function(url, options) { + if (options === undefined) { + options = { + method: "GET", + credentials: "same-origin", + headers: {}, + }; } - }; + 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 }; })(); \ No newline at end of file diff --git a/CTFd/themes/core/templates/base.html b/CTFd/themes/core/templates/base.html index cb73b7e7..e52071f3 100644 --- a/CTFd/themes/core/templates/base.html +++ b/CTFd/themes/core/templates/base.html @@ -4,15 +4,15 @@ {{ get_ctf_name() }} - - - - - - - - + + + + + + + {% block stylesheets %}{% endblock %} {% for stylesheet in get_registered_stylesheets() %} {% if stylesheet.startswith('http') %} @@ -24,17 +24,18 @@ {% endif %} {% endfor %} - - - - - - + + + + + + @@ -142,13 +143,13 @@ - - - - - - - + + + + + + + {% block scripts %} {% endblock %} diff --git a/CTFd/themes/core/templates/challenges.html b/CTFd/themes/core/templates/challenges.html index 6d1a9bf5..a0eec8ac 100644 --- a/CTFd/themes/core/templates/challenges.html +++ b/CTFd/themes/core/templates/challenges.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block stylesheets %} - + {% endblock %} {% block content %} @@ -56,11 +56,11 @@ - - + + {% if admin or not errors %} - - + + {% endif %} - + {% endblock %} diff --git a/CTFd/themes/core/templates/confirm.html b/CTFd/themes/core/templates/confirm.html index 3c204175..6a2d31b3 100644 --- a/CTFd/themes/core/templates/confirm.html +++ b/CTFd/themes/core/templates/confirm.html @@ -59,6 +59,6 @@ {% endblock %} {% block scripts %} - + {% endblock %} diff --git a/CTFd/themes/core/templates/notifications.html b/CTFd/themes/core/templates/notifications.html index 8dbd989d..78465e6b 100644 --- a/CTFd/themes/core/templates/notifications.html +++ b/CTFd/themes/core/templates/notifications.html @@ -22,6 +22,6 @@ {% endblock %} {% block scripts %} - - + + {% endblock %} diff --git a/CTFd/themes/core/templates/reset_password.html b/CTFd/themes/core/templates/reset_password.html index 2408bff1..7a8ec0d7 100644 --- a/CTFd/themes/core/templates/reset_password.html +++ b/CTFd/themes/core/templates/reset_password.html @@ -54,5 +54,5 @@ {% endblock %} {% block scripts %} - + {% endblock %} diff --git a/CTFd/themes/core/templates/scoreboard.html b/CTFd/themes/core/templates/scoreboard.html index e4b8f44c..caefd48b 100644 --- a/CTFd/themes/core/templates/scoreboard.html +++ b/CTFd/themes/core/templates/scoreboard.html @@ -75,7 +75,7 @@ {% endblock %} {% block scripts %} - - - + + + {% endblock %} diff --git a/CTFd/themes/core/templates/settings.html b/CTFd/themes/core/templates/settings.html index af7f4db9..909e061e 100644 --- a/CTFd/themes/core/templates/settings.html +++ b/CTFd/themes/core/templates/settings.html @@ -93,6 +93,6 @@ {% endblock %} {% block scripts %} - - + + {% endblock %} diff --git a/CTFd/themes/core/templates/setup.html b/CTFd/themes/core/templates/setup.html index 501b644e..7a3f5871 100644 --- a/CTFd/themes/core/templates/setup.html +++ b/CTFd/themes/core/templates/setup.html @@ -87,5 +87,5 @@ {% endblock %} {% block scripts %} - + {% endblock %} diff --git a/CTFd/themes/core/templates/teams/team.html b/CTFd/themes/core/templates/teams/team.html index 658fff7e..408f7911 100644 --- a/CTFd/themes/core/templates/teams/team.html +++ b/CTFd/themes/core/templates/teams/team.html @@ -158,9 +158,9 @@ {% endif %} var team_account_id = team_self ? "me" : team_id; - - + + {% if solves %} - + {% endif %} {% endblock %} diff --git a/CTFd/themes/core/templates/teams/team_enrollment.html b/CTFd/themes/core/templates/teams/team_enrollment.html index f3b2e03b..4e3af1ea 100644 --- a/CTFd/themes/core/templates/teams/team_enrollment.html +++ b/CTFd/themes/core/templates/teams/team_enrollment.html @@ -35,9 +35,9 @@ {% endblock %} {% block scripts %} - - + + {% if solves %} - + {% endif %} {% endblock %} diff --git a/CTFd/themes/core/templates/users/user.html b/CTFd/themes/core/templates/users/user.html index 05adeaa4..8ec2f5a3 100644 --- a/CTFd/themes/core/templates/users/user.html +++ b/CTFd/themes/core/templates/users/user.html @@ -129,7 +129,7 @@ var user_self = {{ (user.id == id) | tojson }}; var user_account_id = user_self ? "me" : user_id; - - - + + + {% endblock %} diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py index 4903a276..c9693bbe 100644 --- a/CTFd/utils/initialization/__init__.py +++ b/CTFd/utils/initialization/__init__.py @@ -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'): diff --git a/tests/api/v1/user/test_hints.py b/tests/api/v1/user/test_hints.py index 675f535f..a334986d 100644 --- a/tests/api/v1/user/test_hints.py +++ b/tests/api/v1/user/test_hints.py @@ -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)