diff --git a/CTFd/themes/admin/assets/js/pages/user.js b/CTFd/themes/admin/assets/js/pages/user.js index 04e5fed..8faea93 100644 --- a/CTFd/themes/admin/assets/js/pages/user.js +++ b/CTFd/themes/admin/assets/js/pages/user.js @@ -189,80 +189,70 @@ function emailUser(event) { }); } -function deleteUserSubmission(event) { - event.preventDefault(); - const submission_id = $(this).attr("submission-id"); - const submission_type = $(this).attr("submission-type"); - const submission_challenge = $(this).attr("submission-challenge"); +function deleteSelectedSubmissions(event, target) { + let submissions; + let type; + let title; + switch(target){ + case "solves": + submissions = $("input[data-submission-type=correct]:checked"); + type = "solve"; + title = "Solves" + break; + case "fails": + submissions = $("input[data-submission-type=incorrect]:checked"); + type = "fail"; + title = "Fails" + break; + default: + break; + } - const body = "Are you sure you want to delete {0} submission from {1} for {2}?".format( - htmlEntities(submission_type), - htmlEntities(USER_NAME), - htmlEntities(submission_challenge) - ); - - const row = $(this) - .parent() - .parent(); + let submissionIDs = submissions.map(function() { + return $(this).data("submission-id"); + }); + let target_string = submissionIDs.length === 1 ? type : (type + "s"); ezQuery({ - title: "Delete Submission", - body: body, + title: `Delete ${title}`, + body: `Are you sure you want to delete ${submissionIDs.length} ${target_string}?`, success: function() { - CTFd.fetch("/api/v1/submissions/" + submission_id, { - method: "DELETE", - credentials: "same-origin", - headers: { - Accept: "application/json", - "Content-Type": "application/json" - } - }) - .then(function(response) { - return response.json(); - }) - .then(function(response) { - if (response.success) { - row.remove(); - } - }); + const reqs = []; + for (var subId of submissionIDs) { + reqs.push(CTFd.api.delete_submission({ submissionId: subId })); + } + Promise.all(reqs).then(responses => { + window.location.reload(); + }); } }); } -function deleteUserAward(event) { - event.preventDefault(); - const award_id = $(this).attr("award-id"); - const award_name = $(this).attr("award-name"); - - const body = "Are you sure you want to delete the {0} award from {1}?".format( - htmlEntities(award_name), - htmlEntities(USER_NAME) - ); - - const row = $(this) - .parent() - .parent(); +function deleteSelectedAwards(event) { + let awardIDs = $("input[data-award-id]:checked").map(function() { + return $(this).data("award-id"); + }); + let target = awardIDs.length === 1 ? "award" : "awards"; ezQuery({ - title: "Delete Award", - body: body, + title: `Delete Awards`, + body: `Are you sure you want to delete ${awardIDs.length} ${target}?`, success: function() { - CTFd.fetch("/api/v1/awards/" + award_id, { - method: "DELETE", - credentials: "same-origin", - headers: { - Accept: "application/json", - "Content-Type": "application/json" - } - }) - .then(function(response) { - return response.json(); - }) - .then(function(response) { - if (response.success) { - row.remove(); + const reqs = []; + for (var awardID of awardIDs) { + let req = CTFd.fetch("/api/v1/awards/" + awardID, { + method: "DELETE", + credentials: "same-origin", + headers: { + Accept: "application/json", + "Content-Type": "application/json" } }); + reqs.push(req); + } + Promise.all(reqs).then(responses => { + window.location.reload(); + }); } }); } @@ -425,8 +415,18 @@ $(() => { $("#user-mail-form").submit(emailUser); - $(".delete-submission").click(deleteUserSubmission); - $(".delete-award").click(deleteUserAward); + $("#solves-delete-button").click(function(e){ + deleteSelectedSubmissions(e, "solves") + }); + + $("#fails-delete-button").click(function(e){ + deleteSelectedSubmissions(e, "fails") + }); + + $("#awards-delete-button").click(function(e){ + deleteSelectedAwards(e); + }); + $(".correct-submission").click(correctUserSubmission); $("#user-info-create-form").submit(createUser); diff --git a/CTFd/themes/admin/static/js/pages/user.dev.js b/CTFd/themes/admin/static/js/pages/user.dev.js index 34cb96e..f8d035c 100644 --- a/CTFd/themes/admin/static/js/pages/user.dev.js +++ b/CTFd/themes/admin/static/js/pages/user.dev.js @@ -162,7 +162,7 @@ /***/ (function(module, exports, __webpack_require__) { ; -eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/admin/assets/js/pages/main.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! core/CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _utils = __webpack_require__(/*! core/utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _ezq = __webpack_require__(/*! core/ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _graphs = __webpack_require__(/*! core/graphs */ \"./CTFd/themes/core/assets/js/graphs.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\nfunction createUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-info-create-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n var user_id = response.data.id;\n window.location = _CTFd.default.config.urlRoot + \"/admin/users/\" + user_id;\n } else {\n (0, _jquery.default)(\"#user-info-create-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-info-create-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-info-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction updateUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-info-edit-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location.reload();\n } else {\n (0, _jquery.default)(\"#user-info-edit-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-info-edit-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-info-edit-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction deleteUser(event) {\n event.preventDefault();\n (0, _ezq.ezQuery)({\n title: \"Delete User\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(USER_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location = _CTFd.default.config.urlRoot + \"/admin/users\";\n }\n });\n }\n });\n}\n\nfunction awardUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-award-form\").serializeJSON(true);\n params[\"user_id\"] = USER_ID;\n\n _CTFd.default.fetch(\"/api/v1/awards\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location.reload();\n } else {\n (0, _jquery.default)(\"#user-award-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-award-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-award-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction emailUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-mail-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID + \"/email\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery.default)(\"#user-mail-form > #results\").append((0, _ezq.ezBadge)({\n type: \"success\",\n body: \"E-Mail sent successfully!\"\n }));\n (0, _jquery.default)(\"#user-mail-form\").find(\"input[type=text], textarea\").val(\"\");\n } else {\n (0, _jquery.default)(\"#user-mail-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-mail-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-mail-form\").find(\"input[name={0}], textarea[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction deleteUserSubmission(event) {\n event.preventDefault();\n var submission_id = (0, _jquery.default)(this).attr(\"submission-id\");\n var submission_type = (0, _jquery.default)(this).attr(\"submission-type\");\n var submission_challenge = (0, _jquery.default)(this).attr(\"submission-challenge\");\n var body = \"Are you sure you want to delete {0} submission from {1} for {2}?\".format((0, _utils.htmlEntities)(submission_type), (0, _utils.htmlEntities)(USER_NAME), (0, _utils.htmlEntities)(submission_challenge));\n var row = (0, _jquery.default)(this).parent().parent();\n (0, _ezq.ezQuery)({\n title: \"Delete Submission\",\n body: body,\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/submissions/\" + submission_id, {\n method: \"DELETE\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n row.remove();\n }\n });\n }\n });\n}\n\nfunction deleteUserAward(event) {\n event.preventDefault();\n var award_id = (0, _jquery.default)(this).attr(\"award-id\");\n var award_name = (0, _jquery.default)(this).attr(\"award-name\");\n var body = \"Are you sure you want to delete the {0} award from {1}?\".format((0, _utils.htmlEntities)(award_name), (0, _utils.htmlEntities)(USER_NAME));\n var row = (0, _jquery.default)(this).parent().parent();\n (0, _ezq.ezQuery)({\n title: \"Delete Award\",\n body: body,\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/awards/\" + award_id, {\n method: \"DELETE\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n row.remove();\n }\n });\n }\n });\n}\n\nfunction correctUserSubmission(event) {\n event.preventDefault();\n var challenge_id = (0, _jquery.default)(this).attr(\"challenge-id\");\n var challenge_name = (0, _jquery.default)(this).attr(\"challenge-name\");\n var row = (0, _jquery.default)(this).parent().parent();\n var body = \"Are you sure you want to mark {0} solved for from {1}?\".format((0, _utils.htmlEntities)(challenge_name), (0, _utils.htmlEntities)(USER_NAME));\n var params = {\n provided: \"MARKED AS SOLVED BY ADMIN\",\n user_id: USER_ID,\n team_id: TEAM_ID,\n challenge_id: challenge_id,\n type: \"correct\"\n };\n (0, _ezq.ezQuery)({\n title: \"Mark Correct\",\n body: body,\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/submissions\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n // TODO: Refresh missing and solves instead of reloading\n row.remove();\n window.location.reload();\n }\n });\n }\n });\n}\n\nvar api_funcs = {\n team: [function (x) {\n return _CTFd.default.api.get_team_solves({\n teamId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_team_fails({\n teamId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_team_awards({\n teamId: x\n });\n }],\n user: [function (x) {\n return _CTFd.default.api.get_user_solves({\n userId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_user_fails({\n userId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_user_awards({\n userId: x\n });\n }]\n};\n\nvar createGraphs = function createGraphs(type, id, name, account_id) {\n var _api_funcs$type = _slicedToArray(api_funcs[type], 3),\n solves_func = _api_funcs$type[0],\n fails_func = _api_funcs$type[1],\n awards_func = _api_funcs$type[2];\n\n Promise.all([solves_func(account_id), fails_func(account_id), awards_func(account_id)]).then(function (responses) {\n (0, _graphs.createGraph)(\"score_graph\", \"#score-graph\", responses, type, id, name, account_id);\n (0, _graphs.createGraph)(\"category_breakdown\", \"#categories-pie-graph\", responses, type, id, name, account_id);\n (0, _graphs.createGraph)(\"solve_percentages\", \"#keys-pie-graph\", responses, type, id, name, account_id);\n });\n};\n\nvar updateGraphs = function updateGraphs(type, id, name, account_id) {\n var _api_funcs$type2 = _slicedToArray(api_funcs[type], 3),\n solves_func = _api_funcs$type2[0],\n fails_func = _api_funcs$type2[1],\n awards_func = _api_funcs$type2[2];\n\n Promise.all([solves_func(account_id), fails_func(account_id), awards_func(account_id)]).then(function (responses) {\n (0, _graphs.updateGraph)(\"score_graph\", \"#score-graph\", responses, type, id, name, account_id);\n (0, _graphs.updateGraph)(\"category_breakdown\", \"#categories-pie-graph\", responses, type, id, name, account_id);\n (0, _graphs.updateGraph)(\"solve_percentages\", \"#keys-pie-graph\", responses, type, id, name, account_id);\n });\n};\n\n(0, _jquery.default)(function () {\n (0, _jquery.default)(\".delete-user\").click(deleteUser);\n (0, _jquery.default)(\".edit-user\").click(function (event) {\n (0, _jquery.default)(\"#user-info-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".award-user\").click(function (event) {\n (0, _jquery.default)(\"#user-award-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".email-user\").click(function (event) {\n (0, _jquery.default)(\"#user-email-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".addresses-user\").click(function (event) {\n (0, _jquery.default)(\"#user-addresses-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\"#user-mail-form\").submit(emailUser);\n (0, _jquery.default)(\".delete-submission\").click(deleteUserSubmission);\n (0, _jquery.default)(\".delete-award\").click(deleteUserAward);\n (0, _jquery.default)(\".correct-submission\").click(correctUserSubmission);\n (0, _jquery.default)(\"#user-info-create-form\").submit(createUser);\n (0, _jquery.default)(\"#user-info-edit-form\").submit(updateUser);\n (0, _jquery.default)(\"#user-award-form\").submit(awardUser);\n var type, id, name, account_id;\n var _window$stats_data = window.stats_data;\n type = _window$stats_data.type;\n id = _window$stats_data.id;\n name = _window$stats_data.name;\n account_id = _window$stats_data.account_id;\n createGraphs(type, id, name, account_id);\n setInterval(function () {\n updateGraphs(type, id, name, account_id);\n }, 300000);\n});\n\n//# sourceURL=webpack:///./CTFd/themes/admin/assets/js/pages/user.js?"); +eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/admin/assets/js/pages/main.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! core/CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _utils = __webpack_require__(/*! core/utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _ezq = __webpack_require__(/*! core/ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _graphs = __webpack_require__(/*! core/graphs */ \"./CTFd/themes/core/assets/js/graphs.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\nfunction createUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-info-create-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n var user_id = response.data.id;\n window.location = _CTFd.default.config.urlRoot + \"/admin/users/\" + user_id;\n } else {\n (0, _jquery.default)(\"#user-info-create-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-info-create-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-info-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction updateUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-info-edit-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location.reload();\n } else {\n (0, _jquery.default)(\"#user-info-edit-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-info-edit-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-info-edit-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction deleteUser(event) {\n event.preventDefault();\n (0, _ezq.ezQuery)({\n title: \"Delete User\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(USER_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location = _CTFd.default.config.urlRoot + \"/admin/users\";\n }\n });\n }\n });\n}\n\nfunction awardUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-award-form\").serializeJSON(true);\n params[\"user_id\"] = USER_ID;\n\n _CTFd.default.fetch(\"/api/v1/awards\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location.reload();\n } else {\n (0, _jquery.default)(\"#user-award-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-award-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-award-form\").find(\"input[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction emailUser(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#user-mail-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/users/\" + USER_ID + \"/email\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery.default)(\"#user-mail-form > #results\").append((0, _ezq.ezBadge)({\n type: \"success\",\n body: \"E-Mail sent successfully!\"\n }));\n (0, _jquery.default)(\"#user-mail-form\").find(\"input[type=text], textarea\").val(\"\");\n } else {\n (0, _jquery.default)(\"#user-mail-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#user-mail-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#user-mail-form\").find(\"input[name={0}], textarea[name={0}]\".format(key));\n var input = (0, _jquery.default)(i);\n input.addClass(\"input-filled-invalid\");\n input.removeClass(\"input-filled-valid\");\n });\n }\n });\n}\n\nfunction deleteSelectedSubmissions(event, target) {\n var submissions;\n var type;\n var title;\n\n switch (target) {\n case \"solves\":\n submissions = (0, _jquery.default)(\"input[data-submission-type=correct]:checked\");\n type = \"solve\";\n title = \"Solves\";\n break;\n\n case \"fails\":\n submissions = (0, _jquery.default)(\"input[data-submission-type=incorrect]:checked\");\n type = \"fail\";\n title = \"Fails\";\n break;\n\n default:\n break;\n }\n\n var submissionIDs = submissions.map(function () {\n return (0, _jquery.default)(this).data(\"submission-id\");\n });\n var target_string = submissionIDs.length === 1 ? type : type + \"s\";\n (0, _ezq.ezQuery)({\n title: \"Delete \".concat(title),\n body: \"Are you sure you want to delete \".concat(submissionIDs.length, \" \").concat(target_string, \"?\"),\n success: function success() {\n var reqs = [];\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = submissionIDs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var subId = _step.value;\n reqs.push(_CTFd.default.api.delete_submission({\n submissionId: subId\n }));\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n Promise.all(reqs).then(function (responses) {\n window.location.reload();\n });\n }\n });\n}\n\nfunction deleteSelectedAwards(event) {\n var awardIDs = (0, _jquery.default)(\"input[data-award-id]:checked\").map(function () {\n return (0, _jquery.default)(this).data(\"award-id\");\n });\n var target = awardIDs.length === 1 ? \"award\" : \"awards\";\n (0, _ezq.ezQuery)({\n title: \"Delete Awards\",\n body: \"Are you sure you want to delete \".concat(awardIDs.length, \" \").concat(target, \"?\"),\n success: function success() {\n var reqs = [];\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = awardIDs[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var awardID = _step2.value;\n\n var req = _CTFd.default.fetch(\"/api/v1/awards/\" + awardID, {\n method: \"DELETE\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n }\n });\n\n reqs.push(req);\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return != null) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n Promise.all(reqs).then(function (responses) {\n window.location.reload();\n });\n }\n });\n}\n\nfunction correctUserSubmission(event) {\n event.preventDefault();\n var challenge_id = (0, _jquery.default)(this).attr(\"challenge-id\");\n var challenge_name = (0, _jquery.default)(this).attr(\"challenge-name\");\n var row = (0, _jquery.default)(this).parent().parent();\n var body = \"Are you sure you want to mark {0} solved for from {1}?\".format((0, _utils.htmlEntities)(challenge_name), (0, _utils.htmlEntities)(USER_NAME));\n var params = {\n provided: \"MARKED AS SOLVED BY ADMIN\",\n user_id: USER_ID,\n team_id: TEAM_ID,\n challenge_id: challenge_id,\n type: \"correct\"\n };\n (0, _ezq.ezQuery)({\n title: \"Mark Correct\",\n body: body,\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/submissions\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n // TODO: Refresh missing and solves instead of reloading\n row.remove();\n window.location.reload();\n }\n });\n }\n });\n}\n\nvar api_funcs = {\n team: [function (x) {\n return _CTFd.default.api.get_team_solves({\n teamId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_team_fails({\n teamId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_team_awards({\n teamId: x\n });\n }],\n user: [function (x) {\n return _CTFd.default.api.get_user_solves({\n userId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_user_fails({\n userId: x\n });\n }, function (x) {\n return _CTFd.default.api.get_user_awards({\n userId: x\n });\n }]\n};\n\nvar createGraphs = function createGraphs(type, id, name, account_id) {\n var _api_funcs$type = _slicedToArray(api_funcs[type], 3),\n solves_func = _api_funcs$type[0],\n fails_func = _api_funcs$type[1],\n awards_func = _api_funcs$type[2];\n\n Promise.all([solves_func(account_id), fails_func(account_id), awards_func(account_id)]).then(function (responses) {\n (0, _graphs.createGraph)(\"score_graph\", \"#score-graph\", responses, type, id, name, account_id);\n (0, _graphs.createGraph)(\"category_breakdown\", \"#categories-pie-graph\", responses, type, id, name, account_id);\n (0, _graphs.createGraph)(\"solve_percentages\", \"#keys-pie-graph\", responses, type, id, name, account_id);\n });\n};\n\nvar updateGraphs = function updateGraphs(type, id, name, account_id) {\n var _api_funcs$type2 = _slicedToArray(api_funcs[type], 3),\n solves_func = _api_funcs$type2[0],\n fails_func = _api_funcs$type2[1],\n awards_func = _api_funcs$type2[2];\n\n Promise.all([solves_func(account_id), fails_func(account_id), awards_func(account_id)]).then(function (responses) {\n (0, _graphs.updateGraph)(\"score_graph\", \"#score-graph\", responses, type, id, name, account_id);\n (0, _graphs.updateGraph)(\"category_breakdown\", \"#categories-pie-graph\", responses, type, id, name, account_id);\n (0, _graphs.updateGraph)(\"solve_percentages\", \"#keys-pie-graph\", responses, type, id, name, account_id);\n });\n};\n\n(0, _jquery.default)(function () {\n (0, _jquery.default)(\".delete-user\").click(deleteUser);\n (0, _jquery.default)(\".edit-user\").click(function (event) {\n (0, _jquery.default)(\"#user-info-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".award-user\").click(function (event) {\n (0, _jquery.default)(\"#user-award-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".email-user\").click(function (event) {\n (0, _jquery.default)(\"#user-email-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".addresses-user\").click(function (event) {\n (0, _jquery.default)(\"#user-addresses-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\"#user-mail-form\").submit(emailUser);\n (0, _jquery.default)(\"#solves-delete-button\").click(function (e) {\n deleteSelectedSubmissions(e, \"solves\");\n });\n (0, _jquery.default)(\"#fails-delete-button\").click(function (e) {\n deleteSelectedSubmissions(e, \"fails\");\n });\n (0, _jquery.default)(\"#awards-delete-button\").click(function (e) {\n deleteSelectedAwards(e);\n });\n (0, _jquery.default)(\".correct-submission\").click(correctUserSubmission);\n (0, _jquery.default)(\"#user-info-create-form\").submit(createUser);\n (0, _jquery.default)(\"#user-info-edit-form\").submit(updateUser);\n (0, _jquery.default)(\"#user-award-form\").submit(awardUser);\n var type, id, name, account_id;\n var _window$stats_data = window.stats_data;\n type = _window$stats_data.type;\n id = _window$stats_data.id;\n name = _window$stats_data.name;\n account_id = _window$stats_data.account_id;\n createGraphs(type, id, name, account_id);\n setInterval(function () {\n updateGraphs(type, id, name, account_id);\n }, 300000);\n});\n\n//# sourceURL=webpack:///./CTFd/themes/admin/assets/js/pages/user.js?"); /***/ }) diff --git a/CTFd/themes/admin/templates/users/user.html b/CTFd/themes/admin/templates/users/user.html index 30758de..5da9d80 100644 --- a/CTFd/themes/admin/templates/users/user.html +++ b/CTFd/themes/admin/templates/users/user.html @@ -197,23 +197,45 @@ + Solves - - Solves + + + + + + + + + + + + - - Challenge - Submitted - Category - Value - Time - Delete - + + + + + + + Challenge + Submitted + Category + Value + Time + {% for solve in solves %} + + + + + {{ solve.challenge.name }} @@ -225,13 +247,6 @@ - - - - - {% endfor %} @@ -241,66 +256,101 @@ + Fails - - Fails - - - Challenge - Submitted - Time - Delete - - - - {% for fail in fails %} - - - - {{ fail.challenge.name }} - - - - {{ fail.provided }} - - - - - - - - - - - {% endfor %} - - + + + + + + + + + + + + + + + + + + + + Challenge + Submitted + Time + + + + {% for fail in fails %} + + + + + + + + + {{ fail.challenge.name }} + + + + {{ fail.provided }} + + + + + + {% endfor %} + + + Awards - - Awards + + + + + + + + + + + + - - Name - Description - Date - Value - Category - Icon - Delete - + + + + + + + Name + Description + Date + Value + Category + Icon + {% for award in awards %} + + + + + {{ award.name }} {{ award.description }} @@ -308,15 +358,15 @@ {{ award.value }} {{ award.category }} - {{ award.icon }} + {{ award.icon }} - + {% endfor %}
{{ fail.provided }}
{{ award.description }}