diff --git a/CTFd/cache/__init__.py b/CTFd/cache/__init__.py index 686e6949..19d8047b 100644 --- a/CTFd/cache/__init__.py +++ b/CTFd/cache/__init__.py @@ -46,10 +46,10 @@ def clear_pages(): cache.delete_memoized(get_page) -def clear_user_ips(user_id): - from CTFd.utils.user import get_user_ips +def clear_user_recent_ips(user_id): + from CTFd.utils.user import get_user_recent_ips - cache.delete_memoized(get_user_ips, user_id=user_id) + cache.delete_memoized(get_user_recent_ips, user_id=user_id) def clear_user_session(user_id): diff --git a/CTFd/themes/admin/assets/js/pages/team.js b/CTFd/themes/admin/assets/js/pages/team.js index b89c649b..df57b168 100644 --- a/CTFd/themes/admin/assets/js/pages/team.js +++ b/CTFd/themes/admin/assets/js/pages/team.js @@ -221,6 +221,10 @@ $(() => { $("#team-award-modal").modal("toggle"); }); + $(".addresses-team").click(function(event) { + $("#team-addresses-modal").modal("toggle"); + }); + $("#user-award-form").submit(function(e) { e.preventDefault(); const params = $("#user-award-form").serializeJSON(true); diff --git a/CTFd/themes/admin/assets/js/pages/user.js b/CTFd/themes/admin/assets/js/pages/user.js index 1a70f5cc..04e5fed1 100644 --- a/CTFd/themes/admin/assets/js/pages/user.js +++ b/CTFd/themes/admin/assets/js/pages/user.js @@ -419,6 +419,10 @@ $(() => { $("#user-email-modal").modal("toggle"); }); + $(".addresses-user").click(function(event) { + $("#user-addresses-modal").modal("toggle"); + }); + $("#user-mail-form").submit(emailUser); $(".delete-submission").click(deleteUserSubmission); diff --git a/CTFd/themes/admin/static/js/pages/team.dev.js b/CTFd/themes/admin/static/js/pages/team.dev.js index 66fca878..d345a52e 100644 --- a/CTFd/themes/admin/static/js/pages/team.dev.js +++ b/CTFd/themes/admin/static/js/pages/team.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 createTeam(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#team-info-create-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams\", {\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 team_id = response.data.id;\n window.location = _CTFd.default.config.urlRoot + \"/admin/teams/\" + team_id;\n } else {\n (0, _jquery.default)(\"#team-info-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-info-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-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 updateTeam(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#team-info-edit-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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)(\"#team-info-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-info-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-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\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)(\"#team-captain-form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery.default)(\"#team-captain-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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)(\"#team-captain-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-captain-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-captain-form\").find(\"select[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 (0, _jquery.default)(\".edit-team\").click(function (e) {\n (0, _jquery.default)(\"#team-info-edit-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".edit-captain\").click(function (e) {\n (0, _jquery.default)(\"#team-captain-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".award-team\").click(function (e) {\n (0, _jquery.default)(\"#team-award-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\"#user-award-form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery.default)(\"#user-award-form\").serializeJSON(true);\n params[\"user_id\"] = (0, _jquery.default)(\"#award-member-input\").val();\n params[\"team_id\"] = TEAM_ID;\n (0, _jquery.default)(\"#user-award-form > #results\").empty();\n\n if (!params[\"user_id\"]) {\n (0, _jquery.default)(\"#user-award-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: \"Please select a team member\"\n }));\n return;\n }\n\n params[\"user_id\"] = parseInt(params[\"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 (0, _jquery.default)(\".delete-member\").click(function (e) {\n e.preventDefault();\n var member_id = (0, _jquery.default)(this).attr(\"member-id\");\n var member_name = (0, _jquery.default)(this).attr(\"member-name\");\n var params = {\n user_id: member_id\n };\n var row = (0, _jquery.default)(this).parent().parent();\n (0, _ezq.ezQuery)({\n title: \"Remove Member\",\n body: \"Are you sure you want to remove {0} from {1}?

All of their challenges solves, attempts, awards, and unlocked hints will also be deleted!\".format(\"\" + (0, _utils.htmlEntities)(member_name) + \"\", \"\" + (0, _utils.htmlEntities)(TEAM_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_ID + \"/members\", {\n method: \"DELETE\",\n body: JSON.stringify(params)\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 (0, _jquery.default)(\".delete-team\").click(function (e) {\n (0, _ezq.ezQuery)({\n title: \"Delete Team\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(TEAM_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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/teams\";\n }\n });\n }\n });\n });\n (0, _jquery.default)(\".delete-submission\").click(function (e) {\n e.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)(TEAM_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 (0, _jquery.default)(\".delete-award\").click(function (e) {\n e.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)(TEAM_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 (0, _jquery.default)(\"#team-info-create-form\").submit(createTeam);\n (0, _jquery.default)(\"#team-info-edit-form\").submit(updateTeam);\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/team.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 createTeam(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#team-info-create-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams\", {\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 team_id = response.data.id;\n window.location = _CTFd.default.config.urlRoot + \"/admin/teams/\" + team_id;\n } else {\n (0, _jquery.default)(\"#team-info-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-info-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-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 updateTeam(event) {\n event.preventDefault();\n var params = (0, _jquery.default)(\"#team-info-edit-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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)(\"#team-info-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-info-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-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\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)(\"#team-captain-form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery.default)(\"#team-captain-form\").serializeJSON(true);\n\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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)(\"#team-captain-form > #results\").empty();\n Object.keys(response.errors).forEach(function (key, index) {\n (0, _jquery.default)(\"#team-captain-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: response.errors[key]\n }));\n var i = (0, _jquery.default)(\"#team-captain-form\").find(\"select[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 (0, _jquery.default)(\".edit-team\").click(function (e) {\n (0, _jquery.default)(\"#team-info-edit-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".edit-captain\").click(function (e) {\n (0, _jquery.default)(\"#team-captain-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".award-team\").click(function (e) {\n (0, _jquery.default)(\"#team-award-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\".addresses-team\").click(function (event) {\n (0, _jquery.default)(\"#team-addresses-modal\").modal(\"toggle\");\n });\n (0, _jquery.default)(\"#user-award-form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery.default)(\"#user-award-form\").serializeJSON(true);\n params[\"user_id\"] = (0, _jquery.default)(\"#award-member-input\").val();\n params[\"team_id\"] = TEAM_ID;\n (0, _jquery.default)(\"#user-award-form > #results\").empty();\n\n if (!params[\"user_id\"]) {\n (0, _jquery.default)(\"#user-award-form > #results\").append((0, _ezq.ezBadge)({\n type: \"error\",\n body: \"Please select a team member\"\n }));\n return;\n }\n\n params[\"user_id\"] = parseInt(params[\"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 (0, _jquery.default)(\".delete-member\").click(function (e) {\n e.preventDefault();\n var member_id = (0, _jquery.default)(this).attr(\"member-id\");\n var member_name = (0, _jquery.default)(this).attr(\"member-name\");\n var params = {\n user_id: member_id\n };\n var row = (0, _jquery.default)(this).parent().parent();\n (0, _ezq.ezQuery)({\n title: \"Remove Member\",\n body: \"Are you sure you want to remove {0} from {1}?

All of their challenges solves, attempts, awards, and unlocked hints will also be deleted!\".format(\"\" + (0, _utils.htmlEntities)(member_name) + \"\", \"\" + (0, _utils.htmlEntities)(TEAM_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_ID + \"/members\", {\n method: \"DELETE\",\n body: JSON.stringify(params)\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 (0, _jquery.default)(\".delete-team\").click(function (e) {\n (0, _ezq.ezQuery)({\n title: \"Delete Team\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(TEAM_NAME) + \"\"),\n success: function success() {\n _CTFd.default.fetch(\"/api/v1/teams/\" + TEAM_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/teams\";\n }\n });\n }\n });\n });\n (0, _jquery.default)(\".delete-submission\").click(function (e) {\n e.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)(TEAM_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 (0, _jquery.default)(\".delete-award\").click(function (e) {\n e.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)(TEAM_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 (0, _jquery.default)(\"#team-info-create-form\").submit(createTeam);\n (0, _jquery.default)(\"#team-info-edit-form\").submit(updateTeam);\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/team.js?"); /***/ }) diff --git a/CTFd/themes/admin/static/js/pages/team.min.js b/CTFd/themes/admin/static/js/pages/team.min.js index 85b2a4a9..fd9302c6 100644 --- a/CTFd/themes/admin/static/js/pages/team.min.js +++ b/CTFd/themes/admin/static/js/pages/team.min.js @@ -1 +1 @@ -!function(l){function e(e){for(var t,o,n=e[0],s=e[1],a=e[2],i=0,r=[];i #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-info-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")})})}function m(e){e.preventDefault();var t=(0,i.default)("#team-info-edit-form").serializeJSON(!0);r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#team-info-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-info-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}var p={team:[function(e){return r.default.api.get_team_solves({teamId:e})},function(e){return r.default.api.get_team_fails({teamId:e})},function(e){return r.default.api.get_team_awards({teamId:e})}],user:[function(e){return r.default.api.get_user_solves({userId:e})},function(e){return r.default.api.get_user_fails({userId:e})},function(e){return r.default.api.get_user_awards({userId:e})}]};(0,i.default)(function(){var e,t,o,n;(0,i.default)("#team-captain-form").submit(function(e){e.preventDefault();var t=(0,i.default)("#team-captain-form").serializeJSON(!0);r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#team-captain-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-captain-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-captain-form").find("select[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}),(0,i.default)(".edit-team").click(function(e){(0,i.default)("#team-info-edit-modal").modal("toggle")}),(0,i.default)(".edit-captain").click(function(e){(0,i.default)("#team-captain-modal").modal("toggle")}),(0,i.default)(".award-team").click(function(e){(0,i.default)("#team-award-modal").modal("toggle")}),(0,i.default)("#user-award-form").submit(function(e){e.preventDefault();var t=(0,i.default)("#user-award-form").serializeJSON(!0);t.user_id=(0,i.default)("#award-member-input").val(),t.team_id=TEAM_ID,(0,i.default)("#user-award-form > #results").empty(),t.user_id?(t.user_id=parseInt(t.user_id),r.default.fetch("/api/v1/awards",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-award-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-award-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})):(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:"Please select a team member"}))}),(0,i.default)(".delete-member").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("member-id"),o=(0,i.default)(this).attr("member-name"),n={user_id:t},s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Remove Member",body:"Are you sure you want to remove {0} from {1}?

All of their challenges solves, attempts, awards, and unlocked hints will also be deleted!".format(""+(0,l.htmlEntities)(o)+"",""+(0,l.htmlEntities)(TEAM_NAME)+""),success:function(){r.default.fetch("/api/v1/teams/"+TEAM_ID+"/members",{method:"DELETE",body:JSON.stringify(n)}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}),(0,i.default)(".delete-team").click(function(e){(0,d.ezQuery)({title:"Delete Team",body:"Are you sure you want to delete {0}".format(""+(0,l.htmlEntities)(TEAM_NAME)+""),success:function(){r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=r.default.config.urlRoot+"/admin/teams")})}})}),(0,i.default)(".delete-submission").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("submission-id"),o=(0,i.default)(this).attr("submission-type"),n=(0,i.default)(this).attr("submission-challenge"),s="Are you sure you want to delete {0} submission from {1} for {2}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(TEAM_NAME),(0,l.htmlEntities)(n)),a=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Submission",body:s,success:function(){r.default.fetch("/api/v1/submissions/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&a.remove()})}})}),(0,i.default)(".delete-award").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("award-id"),o=(0,i.default)(this).attr("award-name"),n="Are you sure you want to delete the {0} award from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(TEAM_NAME)),s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Award",body:n,success:function(){r.default.fetch("/api/v1/awards/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}),(0,i.default)("#team-info-create-form").submit(a),(0,i.default)("#team-info-edit-form").submit(m);var s=window.stats_data;e=s.type,t=s.id,o=s.name,n=s.account_id,function(t,o,n,s){var e=u(p[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.createGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.createGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.createGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n),setInterval(function(){!function(t,o,n,s){var e=u(p[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.updateGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.updateGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.updateGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n)},3e5)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var n,s=o("./CTFd/themes/core/assets/js/utils.js"),a=(n=o("./node_modules/jquery/dist/jquery.js"))&&n.__esModule?n:{default:n};t.default=function(){(0,a.default)(":input").each(function(){(0,a.default)(this).data("initial",(0,a.default)(this).val())}),(0,a.default)(".form-control").bind({focus:function(){(0,a.default)(this).addClass("input-filled-valid")},blur:function(){""===(0,a.default)(this).val()&&(0,a.default)(this).removeClass("input-filled-valid")}}),(0,a.default)(".modal").on("show.bs.modal",function(e){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")})}),(0,a.default)(function(){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")}),(0,a.default)("tr[data-href]").click(function(){if(!getSelection().toString()){var e=(0,a.default)(this).attr("data-href");e&&(window.location=e)}return!1}),(0,a.default)("[data-checkbox]").click(function(e){(0,a.default)(e.target).is("input[type=checkbox]")?e.stopImmediatePropagation():((0,a.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation())}),(0,a.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,a.default)(this).prop("checked"),o=(0,a.default)(this).index()+1;(0,a.default)(this).closest("table").find("tr td:nth-child(".concat(o,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,a.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,a.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,a.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,s.makeSortableTables)(),(0,a.default)('[data-toggle="tooltip"]').tooltip()})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=d(o("./CTFd/themes/core/assets/js/fetch.js")),s=d(o("./CTFd/themes/core/assets/js/config.js")),a=o("./CTFd/themes/core/assets/js/api.js");o("./CTFd/themes/core/assets/js/patch.js");var i=d(o("./node_modules/markdown-it/index.js")),r=d(o("./node_modules/jquery/dist/jquery.js")),l=d(o("./CTFd/themes/core/assets/js/ezq.js"));function d(e){return e&&e.__esModule?e:{default:e}}function c(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}var u=new a.API("/"),m={},p={ezq:l.default},f={$:r.default,markdown:function(e){var t=function(t){for(var e=1;e".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(c.format(e.button));return e.success&&(0,r.default)(n).click(function(){e.success()}),e.large&&o.find(".modal-dialog").addClass("modal-lg"),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),o.modal("show"),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),o}function f(e){(0,r.default)("#ezq--notifications-toast-container").length||(0,r.default)("body").append((0,r.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t=l.format(e.title,e.body),o=(0,r.default)(t);if(e.onclose&&(0,r.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick){var n=(0,r.default)(o).find(".toast-body");n.addClass("cursor-pointer"),n.click(function(){e.onclick()})}var s=!1!==e.autohide,a=!1!==e.animation,i=e.delay||1e4;return(0,r.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:s,delay:i,animation:a}),o.toast("show"),o}function j(e){var t=a.format(e.title),o=(0,r.default)(t);"string"==typeof e.body?o.find(".modal-body").append("

".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(m),s=(0,r.default)(u);return o.find(".modal-footer").append(s),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),(0,r.default)(n).click(function(){e.success()}),o.modal("show"),o}function h(e){if(e.target){var t=(0,r.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var o=i.format(e.width),n=a.format(e.title),s=(0,r.default)(n);return s.find(".modal-body").append((0,r.default)(o)),(0,r.default)("main").append(s),s.modal("show")}function _(e){var t={success:d,error:s}[e.type].format(e.body);return(0,r.default)(t)}var g={ezAlert:p,ezToast:f,ezQuery:j,ezProgressBar:h,ezBadge:_};t.default=g},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/whatwg-fetch/fetch.js");var n,s=(n=o("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=s.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=s.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/graphs.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.createGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t);if(l.empty(),void 0===l[0])return void console.log("Couldn't find graph target: "+t);l[0].fn=r.fn(n,s,a,i);var d=r.format(n,s,a,i,o);u.default.newPlot(l[0],d,r.layout,j)},t.updateGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t),d=r.format(n,s,a,i,o);u.default.update(l[0],d,r.layout,j)};var c=n(o("./node_modules/jquery/dist/jquery.js")),u=n(o("./node_modules/plotly.js-basic-dist/plotly-basic.js")),m=n(o("./node_modules/moment/moment.js")),p=o("./CTFd/themes/core/assets/js/utils.js");function n(e){return e&&e.__esModule?e:{default:e}}var f={score_graph:{layout:{title:"Score over Time",paper_bgcolor:"rgba(0,0,0,0)",plot_bgcolor:"rgba(0,0,0,0)",hovermode:"closest",xaxis:{showgrid:!1,showspikes:!0},yaxis:{showgrid:!1,showspikes:!0},legend:{orientation:"h"}},fn:function(e,t,o,n){return"CTFd_score_".concat(e,"_").concat(o,"_").concat(t,"_").concat((new Date).toISOString().slice(0,19))},format:function(e,t,o,n,s){var a=[],i=[],r=s[0].data,l=s[2].data,d=r.concat(l);d.sort(function(e,t){return new Date(e.date)-new Date(t.date)});for(var c=0;c>8*s&255).toString(16)).substr(-2)}return n},t.htmlEntities=function(e){return(0,i.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),o=0;o'),(0,i.default)("th.sort-col").click(function(){var e=(0,i.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort(function(s){return function(e,t){var o=a(e,s),n=a(t,s);return i.default.isNumeric(o)&&i.default.isNumeric(n)?o-n:o.toString().localeCompare(n)}}((0,i.default)(this).index()));this.asc=!this.asc,this.asc||(t=t.reverse());for(var o=0;o #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-info-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")})})}function m(e){e.preventDefault();var t=(0,i.default)("#team-info-edit-form").serializeJSON(!0);r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#team-info-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-info-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}var p={team:[function(e){return r.default.api.get_team_solves({teamId:e})},function(e){return r.default.api.get_team_fails({teamId:e})},function(e){return r.default.api.get_team_awards({teamId:e})}],user:[function(e){return r.default.api.get_user_solves({userId:e})},function(e){return r.default.api.get_user_fails({userId:e})},function(e){return r.default.api.get_user_awards({userId:e})}]};(0,i.default)(function(){var e,t,o,n;(0,i.default)("#team-captain-form").submit(function(e){e.preventDefault();var t=(0,i.default)("#team-captain-form").serializeJSON(!0);r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#team-captain-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#team-captain-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#team-captain-form").find("select[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}),(0,i.default)(".edit-team").click(function(e){(0,i.default)("#team-info-edit-modal").modal("toggle")}),(0,i.default)(".edit-captain").click(function(e){(0,i.default)("#team-captain-modal").modal("toggle")}),(0,i.default)(".award-team").click(function(e){(0,i.default)("#team-award-modal").modal("toggle")}),(0,i.default)(".addresses-team").click(function(e){(0,i.default)("#team-addresses-modal").modal("toggle")}),(0,i.default)("#user-award-form").submit(function(e){e.preventDefault();var t=(0,i.default)("#user-award-form").serializeJSON(!0);t.user_id=(0,i.default)("#award-member-input").val(),t.team_id=TEAM_ID,(0,i.default)("#user-award-form > #results").empty(),t.user_id?(t.user_id=parseInt(t.user_id),r.default.fetch("/api/v1/awards",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-award-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-award-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})):(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:"Please select a team member"}))}),(0,i.default)(".delete-member").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("member-id"),o=(0,i.default)(this).attr("member-name"),n={user_id:t},s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Remove Member",body:"Are you sure you want to remove {0} from {1}?

All of their challenges solves, attempts, awards, and unlocked hints will also be deleted!".format(""+(0,l.htmlEntities)(o)+"",""+(0,l.htmlEntities)(TEAM_NAME)+""),success:function(){r.default.fetch("/api/v1/teams/"+TEAM_ID+"/members",{method:"DELETE",body:JSON.stringify(n)}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}),(0,i.default)(".delete-team").click(function(e){(0,d.ezQuery)({title:"Delete Team",body:"Are you sure you want to delete {0}".format(""+(0,l.htmlEntities)(TEAM_NAME)+""),success:function(){r.default.fetch("/api/v1/teams/"+TEAM_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=r.default.config.urlRoot+"/admin/teams")})}})}),(0,i.default)(".delete-submission").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("submission-id"),o=(0,i.default)(this).attr("submission-type"),n=(0,i.default)(this).attr("submission-challenge"),s="Are you sure you want to delete {0} submission from {1} for {2}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(TEAM_NAME),(0,l.htmlEntities)(n)),a=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Submission",body:s,success:function(){r.default.fetch("/api/v1/submissions/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&a.remove()})}})}),(0,i.default)(".delete-award").click(function(e){e.preventDefault();var t=(0,i.default)(this).attr("award-id"),o=(0,i.default)(this).attr("award-name"),n="Are you sure you want to delete the {0} award from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(TEAM_NAME)),s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Award",body:n,success:function(){r.default.fetch("/api/v1/awards/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}),(0,i.default)("#team-info-create-form").submit(a),(0,i.default)("#team-info-edit-form").submit(m);var s=window.stats_data;e=s.type,t=s.id,o=s.name,n=s.account_id,function(t,o,n,s){var e=u(p[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.createGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.createGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.createGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n),setInterval(function(){!function(t,o,n,s){var e=u(p[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.updateGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.updateGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.updateGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n)},3e5)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var n,s=o("./CTFd/themes/core/assets/js/utils.js"),a=(n=o("./node_modules/jquery/dist/jquery.js"))&&n.__esModule?n:{default:n};t.default=function(){(0,a.default)(":input").each(function(){(0,a.default)(this).data("initial",(0,a.default)(this).val())}),(0,a.default)(".form-control").bind({focus:function(){(0,a.default)(this).addClass("input-filled-valid")},blur:function(){""===(0,a.default)(this).val()&&(0,a.default)(this).removeClass("input-filled-valid")}}),(0,a.default)(".modal").on("show.bs.modal",function(e){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")})}),(0,a.default)(function(){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")}),(0,a.default)("tr[data-href]").click(function(){if(!getSelection().toString()){var e=(0,a.default)(this).attr("data-href");e&&(window.location=e)}return!1}),(0,a.default)("[data-checkbox]").click(function(e){(0,a.default)(e.target).is("input[type=checkbox]")?e.stopImmediatePropagation():((0,a.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation())}),(0,a.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,a.default)(this).prop("checked"),o=(0,a.default)(this).index()+1;(0,a.default)(this).closest("table").find("tr td:nth-child(".concat(o,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,a.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,a.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,a.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,s.makeSortableTables)(),(0,a.default)('[data-toggle="tooltip"]').tooltip()})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=d(o("./CTFd/themes/core/assets/js/fetch.js")),s=d(o("./CTFd/themes/core/assets/js/config.js")),a=o("./CTFd/themes/core/assets/js/api.js");o("./CTFd/themes/core/assets/js/patch.js");var i=d(o("./node_modules/markdown-it/index.js")),r=d(o("./node_modules/jquery/dist/jquery.js")),l=d(o("./CTFd/themes/core/assets/js/ezq.js"));function d(e){return e&&e.__esModule?e:{default:e}}function c(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}var u=new a.API("/"),m={},p={ezq:l.default},f={$:r.default,markdown:function(e){var t=function(t){for(var e=1;e".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(c.format(e.button));return e.success&&(0,r.default)(n).click(function(){e.success()}),e.large&&o.find(".modal-dialog").addClass("modal-lg"),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),o.modal("show"),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),o}function f(e){(0,r.default)("#ezq--notifications-toast-container").length||(0,r.default)("body").append((0,r.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t=l.format(e.title,e.body),o=(0,r.default)(t);if(e.onclose&&(0,r.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick){var n=(0,r.default)(o).find(".toast-body");n.addClass("cursor-pointer"),n.click(function(){e.onclick()})}var s=!1!==e.autohide,a=!1!==e.animation,i=e.delay||1e4;return(0,r.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:s,delay:i,animation:a}),o.toast("show"),o}function j(e){var t=a.format(e.title),o=(0,r.default)(t);"string"==typeof e.body?o.find(".modal-body").append("

".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(m),s=(0,r.default)(u);return o.find(".modal-footer").append(s),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),(0,r.default)(n).click(function(){e.success()}),o.modal("show"),o}function h(e){if(e.target){var t=(0,r.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var o=i.format(e.width),n=a.format(e.title),s=(0,r.default)(n);return s.find(".modal-body").append((0,r.default)(o)),(0,r.default)("main").append(s),s.modal("show")}function _(e){var t={success:d,error:s}[e.type].format(e.body);return(0,r.default)(t)}var g={ezAlert:p,ezToast:f,ezQuery:j,ezProgressBar:h,ezBadge:_};t.default=g},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/whatwg-fetch/fetch.js");var n,s=(n=o("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=s.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=s.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/graphs.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.createGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t);if(l.empty(),void 0===l[0])return void console.log("Couldn't find graph target: "+t);l[0].fn=r.fn(n,s,a,i);var d=r.format(n,s,a,i,o);u.default.newPlot(l[0],d,r.layout,j)},t.updateGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t),d=r.format(n,s,a,i,o);u.default.update(l[0],d,r.layout,j)};var c=n(o("./node_modules/jquery/dist/jquery.js")),u=n(o("./node_modules/plotly.js-basic-dist/plotly-basic.js")),m=n(o("./node_modules/moment/moment.js")),p=o("./CTFd/themes/core/assets/js/utils.js");function n(e){return e&&e.__esModule?e:{default:e}}var f={score_graph:{layout:{title:"Score over Time",paper_bgcolor:"rgba(0,0,0,0)",plot_bgcolor:"rgba(0,0,0,0)",hovermode:"closest",xaxis:{showgrid:!1,showspikes:!0},yaxis:{showgrid:!1,showspikes:!0},legend:{orientation:"h"}},fn:function(e,t,o,n){return"CTFd_score_".concat(e,"_").concat(o,"_").concat(t,"_").concat((new Date).toISOString().slice(0,19))},format:function(e,t,o,n,s){var a=[],i=[],r=s[0].data,l=s[2].data,d=r.concat(l);d.sort(function(e,t){return new Date(e.date)-new Date(t.date)});for(var c=0;c>8*s&255).toString(16)).substr(-2)}return n},t.htmlEntities=function(e){return(0,i.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),o=0;o'),(0,i.default)("th.sort-col").click(function(){var e=(0,i.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort(function(s){return function(e,t){var o=a(e,s),n=a(t,s);return i.default.isNumeric(o)&&i.default.isNumeric(n)?o-n:o.toString().localeCompare(n)}}((0,i.default)(this).index()));this.asc=!this.asc,this.asc||(t=t.reverse());for(var o=0;o #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)(\"#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 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?"); /***/ }) diff --git a/CTFd/themes/admin/static/js/pages/user.min.js b/CTFd/themes/admin/static/js/pages/user.min.js index 9911b7ce..0c3f5f19 100644 --- a/CTFd/themes/admin/static/js/pages/user.min.js +++ b/CTFd/themes/admin/static/js/pages/user.min.js @@ -1 +1 @@ -!function(l){function e(e){for(var t,o,n=e[0],s=e[1],a=e[2],i=0,r=[];i #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-info-create-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")})})}function m(e){e.preventDefault();var t=(0,i.default)("#user-info-edit-form").serializeJSON(!0);r.default.fetch("/api/v1/users/"+USER_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-info-edit-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-info-edit-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-info-edit-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function p(e){e.preventDefault(),(0,d.ezQuery)({title:"Delete User",body:"Are you sure you want to delete {0}".format(""+(0,l.htmlEntities)(USER_NAME)+""),success:function(){r.default.fetch("/api/v1/users/"+USER_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=r.default.config.urlRoot+"/admin/users")})}})}function f(e){e.preventDefault();var t=(0,i.default)("#user-award-form").serializeJSON(!0);t.user_id=USER_ID,r.default.fetch("/api/v1/awards",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-award-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-award-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function j(e){e.preventDefault();var t=(0,i.default)("#user-mail-form").serializeJSON(!0);r.default.fetch("/api/v1/users/"+USER_ID+"/email",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?((0,i.default)("#user-mail-form > #results").append((0,d.ezBadge)({type:"success",body:"E-Mail sent successfully!"})),(0,i.default)("#user-mail-form").find("input[type=text], textarea").val("")):((0,i.default)("#user-mail-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-mail-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-mail-form").find("input[name={0}], textarea[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function h(e){e.preventDefault();var t=(0,i.default)(this).attr("submission-id"),o=(0,i.default)(this).attr("submission-type"),n=(0,i.default)(this).attr("submission-challenge"),s="Are you sure you want to delete {0} submission from {1} for {2}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME),(0,l.htmlEntities)(n)),a=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Submission",body:s,success:function(){r.default.fetch("/api/v1/submissions/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&a.remove()})}})}function _(e){e.preventDefault();var t=(0,i.default)(this).attr("award-id"),o=(0,i.default)(this).attr("award-name"),n="Are you sure you want to delete the {0} award from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME)),s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Award",body:n,success:function(){r.default.fetch("/api/v1/awards/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}function g(e){e.preventDefault();var t=(0,i.default)(this).attr("challenge-id"),o=(0,i.default)(this).attr("challenge-name"),n=(0,i.default)(this).parent().parent(),s="Are you sure you want to mark {0} solved for from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME)),a={provided:"MARKED AS SOLVED BY ADMIN",user_id:USER_ID,team_id:TEAM_ID,challenge_id:t,type:"correct"};(0,d.ezQuery)({title:"Mark Correct",body:s,success:function(){r.default.fetch("/api/v1/submissions",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(a)}).then(function(e){return e.json()}).then(function(e){e.success&&(n.remove(),window.location.reload())})}})}var v={team:[function(e){return r.default.api.get_team_solves({teamId:e})},function(e){return r.default.api.get_team_fails({teamId:e})},function(e){return r.default.api.get_team_awards({teamId:e})}],user:[function(e){return r.default.api.get_user_solves({userId:e})},function(e){return r.default.api.get_user_fails({userId:e})},function(e){return r.default.api.get_user_awards({userId:e})}]};(0,i.default)(function(){var e,t,o,n;(0,i.default)(".delete-user").click(p),(0,i.default)(".edit-user").click(function(e){(0,i.default)("#user-info-modal").modal("toggle")}),(0,i.default)(".award-user").click(function(e){(0,i.default)("#user-award-modal").modal("toggle")}),(0,i.default)(".email-user").click(function(e){(0,i.default)("#user-email-modal").modal("toggle")}),(0,i.default)("#user-mail-form").submit(j),(0,i.default)(".delete-submission").click(h),(0,i.default)(".delete-award").click(_),(0,i.default)(".correct-submission").click(g),(0,i.default)("#user-info-create-form").submit(a),(0,i.default)("#user-info-edit-form").submit(m),(0,i.default)("#user-award-form").submit(f);var s=window.stats_data;e=s.type,t=s.id,o=s.name,n=s.account_id,function(t,o,n,s){var e=u(v[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.createGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.createGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.createGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n),setInterval(function(){!function(t,o,n,s){var e=u(v[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.updateGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.updateGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.updateGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n)},3e5)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var n,s=o("./CTFd/themes/core/assets/js/utils.js"),a=(n=o("./node_modules/jquery/dist/jquery.js"))&&n.__esModule?n:{default:n};t.default=function(){(0,a.default)(":input").each(function(){(0,a.default)(this).data("initial",(0,a.default)(this).val())}),(0,a.default)(".form-control").bind({focus:function(){(0,a.default)(this).addClass("input-filled-valid")},blur:function(){""===(0,a.default)(this).val()&&(0,a.default)(this).removeClass("input-filled-valid")}}),(0,a.default)(".modal").on("show.bs.modal",function(e){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")})}),(0,a.default)(function(){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")}),(0,a.default)("tr[data-href]").click(function(){if(!getSelection().toString()){var e=(0,a.default)(this).attr("data-href");e&&(window.location=e)}return!1}),(0,a.default)("[data-checkbox]").click(function(e){(0,a.default)(e.target).is("input[type=checkbox]")?e.stopImmediatePropagation():((0,a.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation())}),(0,a.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,a.default)(this).prop("checked"),o=(0,a.default)(this).index()+1;(0,a.default)(this).closest("table").find("tr td:nth-child(".concat(o,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,a.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,a.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,a.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,s.makeSortableTables)(),(0,a.default)('[data-toggle="tooltip"]').tooltip()})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=d(o("./CTFd/themes/core/assets/js/fetch.js")),s=d(o("./CTFd/themes/core/assets/js/config.js")),a=o("./CTFd/themes/core/assets/js/api.js");o("./CTFd/themes/core/assets/js/patch.js");var i=d(o("./node_modules/markdown-it/index.js")),r=d(o("./node_modules/jquery/dist/jquery.js")),l=d(o("./CTFd/themes/core/assets/js/ezq.js"));function d(e){return e&&e.__esModule?e:{default:e}}function c(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}var u=new a.API("/"),m={},p={ezq:l.default},f={$:r.default,markdown:function(e){var t=function(t){for(var e=1;e".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(c.format(e.button));return e.success&&(0,r.default)(n).click(function(){e.success()}),e.large&&o.find(".modal-dialog").addClass("modal-lg"),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),o.modal("show"),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),o}function f(e){(0,r.default)("#ezq--notifications-toast-container").length||(0,r.default)("body").append((0,r.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t=l.format(e.title,e.body),o=(0,r.default)(t);if(e.onclose&&(0,r.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick){var n=(0,r.default)(o).find(".toast-body");n.addClass("cursor-pointer"),n.click(function(){e.onclick()})}var s=!1!==e.autohide,a=!1!==e.animation,i=e.delay||1e4;return(0,r.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:s,delay:i,animation:a}),o.toast("show"),o}function j(e){var t=a.format(e.title),o=(0,r.default)(t);"string"==typeof e.body?o.find(".modal-body").append("

".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(m),s=(0,r.default)(u);return o.find(".modal-footer").append(s),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),(0,r.default)(n).click(function(){e.success()}),o.modal("show"),o}function h(e){if(e.target){var t=(0,r.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var o=i.format(e.width),n=a.format(e.title),s=(0,r.default)(n);return s.find(".modal-body").append((0,r.default)(o)),(0,r.default)("main").append(s),s.modal("show")}function _(e){var t={success:d,error:s}[e.type].format(e.body);return(0,r.default)(t)}var g={ezAlert:p,ezToast:f,ezQuery:j,ezProgressBar:h,ezBadge:_};t.default=g},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/whatwg-fetch/fetch.js");var n,s=(n=o("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=s.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=s.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/graphs.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.createGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t);if(l.empty(),void 0===l[0])return void console.log("Couldn't find graph target: "+t);l[0].fn=r.fn(n,s,a,i);var d=r.format(n,s,a,i,o);u.default.newPlot(l[0],d,r.layout,j)},t.updateGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t),d=r.format(n,s,a,i,o);u.default.update(l[0],d,r.layout,j)};var c=n(o("./node_modules/jquery/dist/jquery.js")),u=n(o("./node_modules/plotly.js-basic-dist/plotly-basic.js")),m=n(o("./node_modules/moment/moment.js")),p=o("./CTFd/themes/core/assets/js/utils.js");function n(e){return e&&e.__esModule?e:{default:e}}var f={score_graph:{layout:{title:"Score over Time",paper_bgcolor:"rgba(0,0,0,0)",plot_bgcolor:"rgba(0,0,0,0)",hovermode:"closest",xaxis:{showgrid:!1,showspikes:!0},yaxis:{showgrid:!1,showspikes:!0},legend:{orientation:"h"}},fn:function(e,t,o,n){return"CTFd_score_".concat(e,"_").concat(o,"_").concat(t,"_").concat((new Date).toISOString().slice(0,19))},format:function(e,t,o,n,s){var a=[],i=[],r=s[0].data,l=s[2].data,d=r.concat(l);d.sort(function(e,t){return new Date(e.date)-new Date(t.date)});for(var c=0;c>8*s&255).toString(16)).substr(-2)}return n},t.htmlEntities=function(e){return(0,i.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),o=0;o'),(0,i.default)("th.sort-col").click(function(){var e=(0,i.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort(function(s){return function(e,t){var o=a(e,s),n=a(t,s);return i.default.isNumeric(o)&&i.default.isNumeric(n)?o-n:o.toString().localeCompare(n)}}((0,i.default)(this).index()));this.asc=!this.asc,this.asc||(t=t.reverse());for(var o=0;o #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-info-create-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-info-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")})})}function m(e){e.preventDefault();var t=(0,i.default)("#user-info-edit-form").serializeJSON(!0);r.default.fetch("/api/v1/users/"+USER_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-info-edit-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-info-edit-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-info-edit-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function p(e){e.preventDefault(),(0,d.ezQuery)({title:"Delete User",body:"Are you sure you want to delete {0}".format(""+(0,l.htmlEntities)(USER_NAME)+""),success:function(){r.default.fetch("/api/v1/users/"+USER_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=r.default.config.urlRoot+"/admin/users")})}})}function f(e){e.preventDefault();var t=(0,i.default)("#user-award-form").serializeJSON(!0);t.user_id=USER_ID,r.default.fetch("/api/v1/awards",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?window.location.reload():((0,i.default)("#user-award-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-award-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-award-form").find("input[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function j(e){e.preventDefault();var t=(0,i.default)("#user-mail-form").serializeJSON(!0);r.default.fetch("/api/v1/users/"+USER_ID+"/email",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(t)}).then(function(e){return e.json()}).then(function(s){s.success?((0,i.default)("#user-mail-form > #results").append((0,d.ezBadge)({type:"success",body:"E-Mail sent successfully!"})),(0,i.default)("#user-mail-form").find("input[type=text], textarea").val("")):((0,i.default)("#user-mail-form > #results").empty(),Object.keys(s.errors).forEach(function(e,t){(0,i.default)("#user-mail-form > #results").append((0,d.ezBadge)({type:"error",body:s.errors[e]}));var o=(0,i.default)("#user-mail-form").find("input[name={0}], textarea[name={0}]".format(e)),n=(0,i.default)(o);n.addClass("input-filled-invalid"),n.removeClass("input-filled-valid")}))})}function h(e){e.preventDefault();var t=(0,i.default)(this).attr("submission-id"),o=(0,i.default)(this).attr("submission-type"),n=(0,i.default)(this).attr("submission-challenge"),s="Are you sure you want to delete {0} submission from {1} for {2}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME),(0,l.htmlEntities)(n)),a=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Submission",body:s,success:function(){r.default.fetch("/api/v1/submissions/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&a.remove()})}})}function _(e){e.preventDefault();var t=(0,i.default)(this).attr("award-id"),o=(0,i.default)(this).attr("award-name"),n="Are you sure you want to delete the {0} award from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME)),s=(0,i.default)(this).parent().parent();(0,d.ezQuery)({title:"Delete Award",body:n,success:function(){r.default.fetch("/api/v1/awards/"+t,{method:"DELETE",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){e.success&&s.remove()})}})}function g(e){e.preventDefault();var t=(0,i.default)(this).attr("challenge-id"),o=(0,i.default)(this).attr("challenge-name"),n=(0,i.default)(this).parent().parent(),s="Are you sure you want to mark {0} solved for from {1}?".format((0,l.htmlEntities)(o),(0,l.htmlEntities)(USER_NAME)),a={provided:"MARKED AS SOLVED BY ADMIN",user_id:USER_ID,team_id:TEAM_ID,challenge_id:t,type:"correct"};(0,d.ezQuery)({title:"Mark Correct",body:s,success:function(){r.default.fetch("/api/v1/submissions",{method:"POST",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(a)}).then(function(e){return e.json()}).then(function(e){e.success&&(n.remove(),window.location.reload())})}})}var v={team:[function(e){return r.default.api.get_team_solves({teamId:e})},function(e){return r.default.api.get_team_fails({teamId:e})},function(e){return r.default.api.get_team_awards({teamId:e})}],user:[function(e){return r.default.api.get_user_solves({userId:e})},function(e){return r.default.api.get_user_fails({userId:e})},function(e){return r.default.api.get_user_awards({userId:e})}]};(0,i.default)(function(){var e,t,o,n;(0,i.default)(".delete-user").click(p),(0,i.default)(".edit-user").click(function(e){(0,i.default)("#user-info-modal").modal("toggle")}),(0,i.default)(".award-user").click(function(e){(0,i.default)("#user-award-modal").modal("toggle")}),(0,i.default)(".email-user").click(function(e){(0,i.default)("#user-email-modal").modal("toggle")}),(0,i.default)(".addresses-user").click(function(e){(0,i.default)("#user-addresses-modal").modal("toggle")}),(0,i.default)("#user-mail-form").submit(j),(0,i.default)(".delete-submission").click(h),(0,i.default)(".delete-award").click(_),(0,i.default)(".correct-submission").click(g),(0,i.default)("#user-info-create-form").submit(a),(0,i.default)("#user-info-edit-form").submit(m),(0,i.default)("#user-award-form").submit(f);var s=window.stats_data;e=s.type,t=s.id,o=s.name,n=s.account_id,function(t,o,n,s){var e=u(v[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.createGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.createGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.createGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n),setInterval(function(){!function(t,o,n,s){var e=u(v[t],3),a=e[0],i=e[1],r=e[2];Promise.all([a(s),i(s),r(s)]).then(function(e){(0,c.updateGraph)("score_graph","#score-graph",e,t,o,n,s),(0,c.updateGraph)("category_breakdown","#categories-pie-graph",e,t,o,n,s),(0,c.updateGraph)("solve_percentages","#keys-pie-graph",e,t,o,n,s)})}(e,t,o,n)},3e5)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var n,s=o("./CTFd/themes/core/assets/js/utils.js"),a=(n=o("./node_modules/jquery/dist/jquery.js"))&&n.__esModule?n:{default:n};t.default=function(){(0,a.default)(":input").each(function(){(0,a.default)(this).data("initial",(0,a.default)(this).val())}),(0,a.default)(".form-control").bind({focus:function(){(0,a.default)(this).addClass("input-filled-valid")},blur:function(){""===(0,a.default)(this).val()&&(0,a.default)(this).removeClass("input-filled-valid")}}),(0,a.default)(".modal").on("show.bs.modal",function(e){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")})}),(0,a.default)(function(){(0,a.default)(".form-control").each(function(){(0,a.default)(this).val()&&(0,a.default)(this).addClass("input-filled-valid")}),(0,a.default)("tr[data-href]").click(function(){if(!getSelection().toString()){var e=(0,a.default)(this).attr("data-href");e&&(window.location=e)}return!1}),(0,a.default)("[data-checkbox]").click(function(e){(0,a.default)(e.target).is("input[type=checkbox]")?e.stopImmediatePropagation():((0,a.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation())}),(0,a.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,a.default)(this).prop("checked"),o=(0,a.default)(this).index()+1;(0,a.default)(this).closest("table").find("tr td:nth-child(".concat(o,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,a.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,a.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,a.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,s.makeSortableTables)(),(0,a.default)('[data-toggle="tooltip"]').tooltip()})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=d(o("./CTFd/themes/core/assets/js/fetch.js")),s=d(o("./CTFd/themes/core/assets/js/config.js")),a=o("./CTFd/themes/core/assets/js/api.js");o("./CTFd/themes/core/assets/js/patch.js");var i=d(o("./node_modules/markdown-it/index.js")),r=d(o("./node_modules/jquery/dist/jquery.js")),l=d(o("./CTFd/themes/core/assets/js/ezq.js"));function d(e){return e&&e.__esModule?e:{default:e}}function c(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}var u=new a.API("/"),m={},p={ezq:l.default},f={$:r.default,markdown:function(e){var t=function(t){for(var e=1;e".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(c.format(e.button));return e.success&&(0,r.default)(n).click(function(){e.success()}),e.large&&o.find(".modal-dialog").addClass("modal-lg"),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),o.modal("show"),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),o}function f(e){(0,r.default)("#ezq--notifications-toast-container").length||(0,r.default)("body").append((0,r.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t=l.format(e.title,e.body),o=(0,r.default)(t);if(e.onclose&&(0,r.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick){var n=(0,r.default)(o).find(".toast-body");n.addClass("cursor-pointer"),n.click(function(){e.onclick()})}var s=!1!==e.autohide,a=!1!==e.animation,i=e.delay||1e4;return(0,r.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:s,delay:i,animation:a}),o.toast("show"),o}function j(e){var t=a.format(e.title),o=(0,r.default)(t);"string"==typeof e.body?o.find(".modal-body").append("

".concat(e.body,"

")):o.find(".modal-body").append((0,r.default)(e.body));var n=(0,r.default)(m),s=(0,r.default)(u);return o.find(".modal-footer").append(s),o.find(".modal-footer").append(n),(0,r.default)("main").append(o),(0,r.default)(o).on("hidden.bs.modal",function(){(0,r.default)(this).modal("dispose")}),(0,r.default)(n).click(function(){e.success()}),o.modal("show"),o}function h(e){if(e.target){var t=(0,r.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var o=i.format(e.width),n=a.format(e.title),s=(0,r.default)(n);return s.find(".modal-body").append((0,r.default)(o)),(0,r.default)("main").append(s),s.modal("show")}function _(e){var t={success:d,error:s}[e.type].format(e.body);return(0,r.default)(t)}var g={ezAlert:p,ezToast:f,ezQuery:j,ezProgressBar:h,ezBadge:_};t.default=g},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,o("./node_modules/whatwg-fetch/fetch.js");var n,s=(n=o("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=s.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=s.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/graphs.js":function(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.createGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t);if(l.empty(),void 0===l[0])return void console.log("Couldn't find graph target: "+t);l[0].fn=r.fn(n,s,a,i);var d=r.format(n,s,a,i,o);u.default.newPlot(l[0],d,r.layout,j)},t.updateGraph=function(e,t,o,n,s,a,i){var r=f[e],l=(0,c.default)(t),d=r.format(n,s,a,i,o);u.default.update(l[0],d,r.layout,j)};var c=n(o("./node_modules/jquery/dist/jquery.js")),u=n(o("./node_modules/plotly.js-basic-dist/plotly-basic.js")),m=n(o("./node_modules/moment/moment.js")),p=o("./CTFd/themes/core/assets/js/utils.js");function n(e){return e&&e.__esModule?e:{default:e}}var f={score_graph:{layout:{title:"Score over Time",paper_bgcolor:"rgba(0,0,0,0)",plot_bgcolor:"rgba(0,0,0,0)",hovermode:"closest",xaxis:{showgrid:!1,showspikes:!0},yaxis:{showgrid:!1,showspikes:!0},legend:{orientation:"h"}},fn:function(e,t,o,n){return"CTFd_score_".concat(e,"_").concat(o,"_").concat(t,"_").concat((new Date).toISOString().slice(0,19))},format:function(e,t,o,n,s){var a=[],i=[],r=s[0].data,l=s[2].data,d=r.concat(l);d.sort(function(e,t){return new Date(e.date)-new Date(t.date)});for(var c=0;c>8*s&255).toString(16)).substr(-2)}return n},t.htmlEntities=function(e){return(0,i.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),o=0;o'),(0,i.default)("th.sort-col").click(function(){var e=(0,i.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort(function(s){return function(e,t){var o=a(e,s),n=a(t,s);return i.default.isNumeric(o)&&i.default.isNumeric(n)?o-n:o.toString().localeCompare(n)}}((0,i.default)(this).index()));this.asc=!this.asc,this.asc||(t=t.reverse());for(var o=0;o +
+ + + + + + + + + + {% for addr in addrs %} + + + + + + {% endfor %} + +
UserIP AddressLast Seen
+ + {{ addr.user.name }} + + {{ addr.ip }} + +
+
+
diff --git a/CTFd/themes/admin/templates/modals/users/addresses.html b/CTFd/themes/admin/templates/modals/users/addresses.html new file mode 100644 index 00000000..218a64ee --- /dev/null +++ b/CTFd/themes/admin/templates/modals/users/addresses.html @@ -0,0 +1,22 @@ +
+
+ + + + + + + + + {% for addr in addrs %} + + + + + {% endfor %} + +
IP AddressLast Seen
{{ addr.ip }} + +
+
+
diff --git a/CTFd/themes/admin/templates/teams/team.html b/CTFd/themes/admin/templates/teams/team.html index 9fb9d973..f5cbc4f2 100644 --- a/CTFd/themes/admin/templates/teams/team.html +++ b/CTFd/themes/admin/templates/teams/team.html @@ -61,6 +61,22 @@
+ +

{{ team.name }}

@@ -109,6 +125,7 @@ points {% endif %} +
+
+ + + +
@@ -356,37 +378,6 @@
- -
-
- -

IP Addresses

- - - - - - - - - {% for addr in addrs %} - - - - - - {% endfor %} - -
UserIP AddressLast Seen
- - {{ addr.user.name }} - - {{ addr.ip }} - -
-
-
-
{% endblock %} diff --git a/CTFd/themes/admin/templates/users/user.html b/CTFd/themes/admin/templates/users/user.html index a6147286..893be459 100644 --- a/CTFd/themes/admin/templates/users/user.html +++ b/CTFd/themes/admin/templates/users/user.html @@ -52,6 +52,22 @@
+ +

{{ user.name }}

@@ -112,6 +128,7 @@ points {% endif %} +
+
+ + + +
@@ -335,31 +357,6 @@ - -
-
- -

IP Addresses

- - - - - - - - {% for addr in addrs %} - - - - - {% endfor %} - -
IP AddressLast Seen
{{ addr.ip }} - -
-
-
- {% endblock %} diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py index 19aff5d9..73045840 100644 --- a/CTFd/utils/initialization/__init__.py +++ b/CTFd/utils/initialization/__init__.py @@ -7,7 +7,7 @@ from flask import abort, redirect, render_template, request, session, url_for from sqlalchemy.exc import IntegrityError, InvalidRequestError from werkzeug.wsgi import DispatcherMiddleware -from CTFd.cache import clear_user_ips +from CTFd.cache import clear_user_recent_ips from CTFd.exceptions import UserNotFoundException, UserTokenExpiredException from CTFd.models import Tracking, db from CTFd.utils import config, get_config, markdown @@ -42,7 +42,7 @@ from CTFd.utils.security.csrf import generate_nonce from CTFd.utils.user import ( authed, get_current_user_attrs, - get_current_user_ips, + get_current_user_recent_ips, get_current_team_attrs, get_ip, is_admin, @@ -181,18 +181,20 @@ def init_request_processors(app): return if authed(): - user_ips = get_current_user_ips() + user_ips = get_current_user_recent_ips() ip = get_ip() + track = None - if ip not in user_ips: - track = Tracking(ip=get_ip(), user_id=session["id"]) - db.session.add(track) - else: - if request.method != "GET": - track = Tracking.query.filter_by( - ip=get_ip(), user_id=session["id"] - ).first() + if (ip not in user_ips) or (request.method != "GET"): + track = Tracking.query.filter_by( + ip=get_ip(), user_id=session["id"] + ).first() + + if track: track.date = datetime.datetime.utcnow() + else: + track = Tracking(ip=get_ip(), user_id=session["id"]) + db.session.add(track) if track: try: @@ -200,7 +202,7 @@ def init_request_processors(app): except (InvalidRequestError, IntegrityError): db.session.rollback() logout_user() - clear_user_ips(user_id=session["id"]) + clear_user_recent_ips(user_id=session["id"]) @app.before_request def banned(): diff --git a/CTFd/utils/user/__init__.py b/CTFd/utils/user/__init__.py index 5186e2b0..7f21dcab 100644 --- a/CTFd/utils/user/__init__.py +++ b/CTFd/utils/user/__init__.py @@ -120,21 +120,22 @@ def get_ip(req=None): return remote_addr -def get_current_user_ips(): +def get_current_user_recent_ips(): if authed(): - return get_user_ips(user_id=session["id"]) + return get_user_recent_ips(user_id=session["id"]) else: return None @cache.memoize(timeout=60) -def get_user_ips(user_id): +def get_user_recent_ips(user_id): + hour_ago = datetime.datetime.now() - datetime.timedelta(hours=1) addrs = ( Tracking.query.with_entities(Tracking.ip.distinct()) - .filter_by(user_id=user_id) + .filter(Tracking.user_id == user_id, Tracking.date >= hour_ago) .all() ) - return [ip for ip, in addrs] + return set([ip for (ip,) in addrs]) def get_wrong_submissions_per_minute(account_id):