Skip to content

Commit

Permalink
Fix changing profile settings from admin and user settings pages (CTF…
Browse files Browse the repository at this point in the history
…d#1290)

* Fixes users/admins being able to remove profile settings
  • Loading branch information
ColdHeat authored Mar 14, 2020
1 parent 123d72a commit 64aa553
Show file tree
Hide file tree
Showing 28 changed files with 43 additions and 29 deletions.
6 changes: 6 additions & 0 deletions CTFd/themes/admin/assets/js/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import "bootstrap/dist/js/bootstrap.bundle";
import $ from "jquery";

export default () => {
// TODO: This is kind of a hack to mimic a React-like state construct.
// It should be removed once we have a real front-end framework in place.
$(":input").each(function() {
$(this).data("initial", $(this).val());
});

$(".form-control").bind({
focus: function() {
$(this).addClass("input-filled-valid");
Expand Down
4 changes: 2 additions & 2 deletions CTFd/themes/admin/static/js/core.dev.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/challenge.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/configs.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/editor.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/main.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/notifications.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/pages.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/reset.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/scoreboard.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/statistics.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/submissions.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/team.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/user.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/admin/static/js/pages/users.min.js

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions CTFd/themes/core/assets/js/pages/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ function profileUpdate(event) {
const $form = $(this);
let params = $form.serializeJSON(true);

// Special case country to allow for removals
params.country = $form.serializeJSON(false)["country"];

CTFd.api.patch_user_private({}, params).then(response => {
if (response.success) {
$("#results").html(success_template);
Expand Down
6 changes: 6 additions & 0 deletions CTFd/themes/core/assets/js/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import "bootstrap/dist/js/bootstrap.bundle";
import $ from "jquery";

export default () => {
// TODO: This is kind of a hack to mimic a React-like state construct.
// It should be removed once we have a real front-end framework in place.
$(":input").each(function() {
$(this).data("initial", $(this).val());
});

$(".form-control").bind({
focus: function() {
$(this).removeClass("input-filled-invalid");
Expand Down
5 changes: 5 additions & 0 deletions CTFd/themes/core/assets/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ $.fn.serializeJSON = function(omit_nulls) {
if (omit_nulls) {
if (x.value !== null && x.value !== "") {
params[x.name] = x.value;
} else {
let input = form.find(`:input[name=${x.name}]`);
if (input.data("initial") !== input.val()) {
params[x.name] = x.value;
}
}
} else {
params[x.name] = x.value;
Expand Down
4 changes: 2 additions & 2 deletions CTFd/themes/core/static/js/core.dev.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/challenges.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/main.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/notifications.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/scoreboard.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/settings.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
/***/ (function(module, exports, __webpack_require__) {

;
eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/core/assets/js/pages/main.js\");\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! ../CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _ezq = __webpack_require__(/*! ../ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar error_template = '<div class=\"alert alert-danger alert-dismissable\" role=\"alert\">\\n' + ' <span class=\"sr-only\">Error:</span>\\n' + \" {0}\\n\" + ' <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button>\\n' + \"</div>\";\nvar success_template = '<div class=\"alert alert-success alert-dismissable submit-row\" role=\"alert\">\\n' + \" <strong>Success!</strong>\\n\" + \" Your profile has been updated\\n\" + ' <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button>\\n' + \"</div>\";\n\nfunction profileUpdate(event) {\n event.preventDefault();\n (0, _jquery.default)(\"#results\").empty();\n var $form = (0, _jquery.default)(this);\n var params = $form.serializeJSON(true); // Special case country to allow for removals\n\n params.country = $form.serializeJSON(false)[\"country\"];\n\n _CTFd.default.api.patch_user_private({}, params).then(function (response) {\n if (response.success) {\n (0, _jquery.default)(\"#results\").html(success_template);\n } else if (\"errors\" in response) {\n Object.keys(response.errors).map(function (error) {\n var i = $form.find(\"input[name={0}]\".format(error));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n var error_msg = response.errors[error];\n (0, _jquery.default)(\"#results\").append(error_template.format(error_msg));\n });\n }\n });\n}\n\nfunction tokenGenerate(event) {\n event.preventDefault();\n var $form = (0, _jquery.default)(this);\n var params = $form.serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/tokens\", {\n method: \"POST\",\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n var body = (0, _jquery.default)(\"\\n <p>Please copy your API Key, it won't be shown again!</p>\\n <div class=\\\"input-group mb-3\\\">\\n <input type=\\\"text\\\" id=\\\"user-token-result\\\" class=\\\"form-control\\\" value=\\\"\".concat(response.data.value, \"\\\" readonly>\\n <div class=\\\"input-group-append\\\">\\n <button class=\\\"btn btn-outline-secondary\\\" type=\\\"button\\\">\\n <i class=\\\"fas fa-clipboard\\\"></i>\\n </button>\\n </div>\\n </div>\\n \"));\n body.find(\"button\").click(function (event) {\n (0, _utils.copyToClipboard)(event, \"#user-token-result\");\n });\n (0, _ezq.ezAlert)({\n title: \"API Key Generated\",\n body: body,\n button: \"Got it!\",\n large: true\n });\n }\n });\n}\n\nfunction deleteToken(event) {\n event.preventDefault();\n var $elem = (0, _jquery.default)(this);\n var id = $elem.data(\"token-id\");\n (0, _ezq.ezQuery)({\n title: \"Delete Token\",\n body: \"Are you sure you want to delete this token?\",\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/tokens/\" + id, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n $elem.parent().parent().remove();\n }\n });\n }\n });\n}\n\n(0, _jquery.default)(function () {\n (0, _jquery.default)(\"#user-profile-form\").submit(profileUpdate);\n (0, _jquery.default)(\"#user-token-form\").submit(tokenGenerate);\n (0, _jquery.default)(\".delete-token\").click(deleteToken);\n (0, _jquery.default)(\".nav-pills a\").click(function (event) {\n window.location.hash = this.hash;\n }); // Load location hash\n\n var hash = window.location.hash;\n\n if (hash) {\n hash = hash.replace(\"<>[]'\\\"\", \"\");\n (0, _jquery.default)('.nav-pills a[href=\"' + hash + '\"]').tab(\"show\");\n }\n});\n\n//# sourceURL=webpack:///./CTFd/themes/core/assets/js/pages/settings.js?");
eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/core/assets/js/pages/main.js\");\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! ../CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _ezq = __webpack_require__(/*! ../ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar error_template = '<div class=\"alert alert-danger alert-dismissable\" role=\"alert\">\\n' + ' <span class=\"sr-only\">Error:</span>\\n' + \" {0}\\n\" + ' <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button>\\n' + \"</div>\";\nvar success_template = '<div class=\"alert alert-success alert-dismissable submit-row\" role=\"alert\">\\n' + \" <strong>Success!</strong>\\n\" + \" Your profile has been updated\\n\" + ' <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><span aria-hidden=\"true\">×</span></button>\\n' + \"</div>\";\n\nfunction profileUpdate(event) {\n event.preventDefault();\n (0, _jquery.default)(\"#results\").empty();\n var $form = (0, _jquery.default)(this);\n var params = $form.serializeJSON(true);\n\n _CTFd.default.api.patch_user_private({}, params).then(function (response) {\n if (response.success) {\n (0, _jquery.default)(\"#results\").html(success_template);\n } else if (\"errors\" in response) {\n Object.keys(response.errors).map(function (error) {\n var i = $form.find(\"input[name={0}]\".format(error));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n var error_msg = response.errors[error];\n (0, _jquery.default)(\"#results\").append(error_template.format(error_msg));\n });\n }\n });\n}\n\nfunction tokenGenerate(event) {\n event.preventDefault();\n var $form = (0, _jquery.default)(this);\n var params = $form.serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/tokens\", {\n method: \"POST\",\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n var body = (0, _jquery.default)(\"\\n <p>Please copy your API Key, it won't be shown again!</p>\\n <div class=\\\"input-group mb-3\\\">\\n <input type=\\\"text\\\" id=\\\"user-token-result\\\" class=\\\"form-control\\\" value=\\\"\".concat(response.data.value, \"\\\" readonly>\\n <div class=\\\"input-group-append\\\">\\n <button class=\\\"btn btn-outline-secondary\\\" type=\\\"button\\\">\\n <i class=\\\"fas fa-clipboard\\\"></i>\\n </button>\\n </div>\\n </div>\\n \"));\n body.find(\"button\").click(function (event) {\n (0, _utils.copyToClipboard)(event, \"#user-token-result\");\n });\n (0, _ezq.ezAlert)({\n title: \"API Key Generated\",\n body: body,\n button: \"Got it!\",\n large: true\n });\n }\n });\n}\n\nfunction deleteToken(event) {\n event.preventDefault();\n var $elem = (0, _jquery.default)(this);\n var id = $elem.data(\"token-id\");\n (0, _ezq.ezQuery)({\n title: \"Delete Token\",\n body: \"Are you sure you want to delete this token?\",\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/tokens/\" + id, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n $elem.parent().parent().remove();\n }\n });\n }\n });\n}\n\n(0, _jquery.default)(function () {\n (0, _jquery.default)(\"#user-profile-form\").submit(profileUpdate);\n (0, _jquery.default)(\"#user-token-form\").submit(tokenGenerate);\n (0, _jquery.default)(\".delete-token\").click(deleteToken);\n (0, _jquery.default)(\".nav-pills a\").click(function (event) {\n window.location.hash = this.hash;\n }); // Load location hash\n\n var hash = window.location.hash;\n\n if (hash) {\n hash = hash.replace(\"<>[]'\\\"\", \"\");\n (0, _jquery.default)('.nav-pills a[href=\"' + hash + '\"]').tab(\"show\");\n }\n});\n\n//# sourceURL=webpack:///./CTFd/themes/core/assets/js/pages/settings.js?");

/***/ })

Expand Down
2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/settings.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/setup.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/stats.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CTFd/themes/core/static/js/pages/teams/private.min.js

Large diffs are not rendered by default.

0 comments on commit 64aa553

Please sign in to comment.