diff --git a/CTFd/plugins/UserChallengeManagement/__init__.py b/CTFd/plugins/UserChallengeManagement/__init__.py index f5cf19703f..788e48b106 100644 --- a/CTFd/plugins/UserChallengeManagement/__init__.py +++ b/CTFd/plugins/UserChallengeManagement/__init__.py @@ -1,68 +1,98 @@ -from flask import render_template,request,Blueprint +from flask import render_template,request,Blueprint, url_for, abort from pathlib import Path from CTFd.utils.plugins import override_template from CTFd.plugins import register_plugin_assets_directory from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class from CTFd.utils.user import get_current_user -from CTFd.models import db +from CTFd.models import Challenges, Solves, Flags +from CTFd.utils.decorators import authed_only + def load(app): - app.db.create_all() + Challenges userChallenge = Blueprint('userChallenge',__name__,template_folder='templates') app.register_blueprint(userChallenge,url_prefix='/userChallenge') + #register_plugin_assets_directory(app, base_path ='/plugins/UserChallengeManagement/assets/') + + registerTemplate('users/private.html','newUserPage.html') + @app.route('/userChallenge/challenges',methods=['GET']) + @authed_only def view_challenges(): #TODO: add custom html extension of admin/challenges/challenges # change methods to check for rights and only display challenges by user # add custom html to change challenge editing to be available to users # - # add other plugin to modify challenge creation? - + # add other plugin to modify challenge creation? + + q = request.args.get("q") field = request.args.get("field") - filters = [get_current_user().id] - query = UserChallenges.query.order_by(UserChallenges.id.asc()) + query = Challenges.query.filter(Challenges.user == get_current_user().id).order_by(Challenges.id.asc()) challenges = query.all() total = query.count() # return render_template('userChallenges.html',challenges=challenges,total=total,q=q,field=field) return render_template('userChallenges.html',challenges=challenges,total = total) + @app.route('/userChallenge/challenges/new',methods=['GET']) + @authed_only def view_newChallenge(): types = CHALLENGE_CLASSES.keys() - return render_template('userChallenge/createUserChallenge.html',types=types) - - - registerTemplate('users/private.html','newUserPage.html') - - register_plugin_assets_directory(app, base_path ='plugins/UserChallengeManagement/assets/') - + return render_template('createUserChallenge.html',types=types) + + @app.route('userChallenge/challenges/') + def updateChallenge(challenge_id): + #TODO: update logic to work with plugin + challenges = dict( + Challenges.query.with_entities(Challenges.id, Challenges.name).all() + ) + challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() + solves = ( + Solves.query.filter_by(challenge_id=challenge.id) + .order_by(Solves.date.asc()) + .all() + ) + flags = Flags.query.filter_by(challenge_id=challenge.id).all() + + try: + challenge_class = get_chal_class(challenge.type) + except KeyError: + abort( + 500, + f"The underlying challenge type ({challenge.type}) is not installed. This challenge can not be loaded.", + ) + + update_j2 = render_template( + challenge_class.templates["update"].lstrip("/"), challenge=challenge + ) + + update_script = url_for( + "views.static_html", route=challenge_class.scripts["update"].lstrip("/") + ) + return render_template( + "editUserChallenge", + update_template=update_j2, + update_script=update_script, + challenge=challenge, + challenges=challenges, + solves=solves, + flags=flags, + ) def registerTemplate(old_path, new_path): dir_path = Path(__file__).parent.resolve() - template_path = dir_path/'templates'/new_path override_template(old_path,open(template_path).read()) - -class UserChallenges(db.Model): - __tablename__ = "UserChallenges" - id = db.Column(db.Integer, primary_key=True) - user = db.Column(db.Integer,db.ForeignKey('users.id')) - challenge = db.Column(db.Integer,db.ForeignKey('challenges.id')) - - - def __init__(self,user,challenge): - self.user = user - self.challenge = challenge diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/challenge-board.scss b/CTFd/plugins/UserChallengeManagement/assets/css/challenge-board.scss deleted file mode 100644 index ef6bbbd14d..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/challenge-board.scss +++ /dev/null @@ -1,68 +0,0 @@ -.chal-desc { - padding-left: 30px; - padding-right: 30px; - font-size: 14px; -} - -.chal-desc img { - max-width: 100%; - height: auto; -} - -.modal-content { - border-radius: 0px; - max-width: 1000px; - padding: 1em; - margin: 0 auto; -} - -.btn-info { - background-color: #5b7290 !important; -} - -.badge-info { - background-color: #5b7290 !important; -} - -.challenge-button { - box-shadow: 3px 3px 3px grey; -} - -.solved-challenge { - background-color: #37d63e !important; - opacity: 0.4; - border: none; -} - -.corner-button-check { - margin-top: -10px; - margin-right: 25px; - position: absolute; - right: 0; -} - -.key-submit .btn { - height: 51px; -} - -#challenge-window .form-control { - position: relative; - display: block; - padding: 0.8em; - border-radius: 0; - background: #f0f0f0; - color: #aaa; - font-weight: 400; - font-family: "Avenir Next", "Helvetica Neue", Helvetica, Arial, sans-serif; - -webkit-appearance: none; - height: auto !important; -} - -#challenge-window .form-control:focus { - background-color: transparent; - border-color: #a3d39c; - box-shadow: 0 0 0 0.1rem #a3d39c; - transition: - background-color 0.3s, - border-color 0.3s; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/award-icons.scss b/CTFd/plugins/UserChallengeManagement/assets/css/includes/award-icons.scss deleted file mode 100644 index 149f39ac22..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/award-icons.scss +++ /dev/null @@ -1,39 +0,0 @@ -.award-icon { - font-family: "Font Awesome 5 Free", "Font Awesome 5 Free Offline"; - font-weight: 900; - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: inline-block; - font-style: normal; - font-variant: normal; - text-rendering: auto; - line-height: 1; -} - -.award-shield:before { - content: "\f3ed"; -} -.award-bug:before { - content: "\f188"; -} -.award-crown:before { - content: "\f521"; -} -.award-crosshairs:before { - content: "\f05b"; -} -.award-ban:before { - content: "\f05e"; -} -.award-lightning:before { - content: "\f0e7"; -} -.award-code:before { - content: "\f121"; -} -.award-cowboy:before { - content: "\f8c0"; -} -.award-angry:before { - content: "\f556"; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/easymde.scss b/CTFd/plugins/UserChallengeManagement/assets/css/includes/easymde.scss deleted file mode 100644 index fa6f858170..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/easymde.scss +++ /dev/null @@ -1,381 +0,0 @@ -.CodeMirror.cm-s-easymde { - box-sizing: border-box; - height: auto; - border: 1px solid lightgray; - padding: 10px; - font: inherit; - z-index: 0; - word-wrap: break-word; -} - -.CodeMirror-scroll { - overflow-y: hidden; - overflow-x: auto; -} - -.editor-toolbar { - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - padding: 0 10px; - border-top: 1px solid #bbb; - border-left: 1px solid #bbb; - border-right: 1px solid #bbb; -} - -.editor-toolbar:after, -.editor-toolbar:before { - display: block; - content: " "; - height: 1px; -} - -.editor-toolbar:before { - margin-bottom: 8px; -} - -.editor-toolbar:after { - margin-top: 8px; -} - -.editor-toolbar.fullscreen { - width: 100%; - height: 50px; - padding-top: 10px; - padding-bottom: 10px; - box-sizing: border-box; - background: #fff; - border: 0; - position: fixed; - top: 0; - left: 0; - opacity: 1; - z-index: 9; -} - -.editor-toolbar.fullscreen::before { - width: 20px; - height: 50px; - background: -moz-linear-gradient( - left, - rgba(255, 255, 255, 1) 0%, - rgba(255, 255, 255, 0) 100% - ); - background: -webkit-gradient( - linear, - left top, - right top, - color-stop(0%, rgba(255, 255, 255, 1)), - color-stop(100%, rgba(255, 255, 255, 0)) - ); - background: -webkit-linear-gradient( - left, - rgba(255, 255, 255, 1) 0%, - rgba(255, 255, 255, 0) 100% - ); - background: -o-linear-gradient( - left, - rgba(255, 255, 255, 1) 0%, - rgba(255, 255, 255, 0) 100% - ); - background: -ms-linear-gradient( - left, - rgba(255, 255, 255, 1) 0%, - rgba(255, 255, 255, 0) 100% - ); - background: linear-gradient( - to right, - rgba(255, 255, 255, 1) 0%, - rgba(255, 255, 255, 0) 100% - ); - position: fixed; - top: 0; - left: 0; - margin: 0; - padding: 0; -} - -.editor-toolbar.fullscreen::after { - width: 20px; - height: 50px; - background: -moz-linear-gradient( - left, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 100% - ); - background: -webkit-gradient( - linear, - left top, - right top, - color-stop(0%, rgba(255, 255, 255, 0)), - color-stop(100%, rgba(255, 255, 255, 1)) - ); - background: -webkit-linear-gradient( - left, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 100% - ); - background: -o-linear-gradient( - left, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 100% - ); - background: -ms-linear-gradient( - left, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 100% - ); - background: linear-gradient( - to right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 100% - ); - position: fixed; - top: 0; - right: 0; - margin: 0; - padding: 0; -} - -.editor-toolbar button, -.editor-toolbar .easymde-dropdown { - background: transparent; - display: inline-block; - text-align: center; - text-decoration: none !important; - height: 30px; - margin: 0; - padding: 0; - border: 1px solid transparent; - border-radius: 3px; - cursor: pointer; -} - -.editor-toolbar button { - width: 30px; -} - -.editor-toolbar button.active, -.editor-toolbar button:hover { - background: #fcfcfc; - border-color: #95a5a6; -} - -.editor-toolbar i.separator { - display: inline-block; - width: 0; - border-left: 1px solid #d9d9d9; - border-right: 1px solid #fff; - color: transparent; - text-indent: -10px; - margin: 0 6px; -} - -.editor-toolbar button:after { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - font-size: 65%; - vertical-align: text-bottom; - position: relative; - top: 2px; -} - -.editor-toolbar button.heading-1:after { - content: "1"; -} - -.editor-toolbar button.heading-2:after { - content: "2"; -} - -.editor-toolbar button.heading-3:after { - content: "3"; -} - -.editor-toolbar button.heading-bigger:after { - content: "▲"; -} - -.editor-toolbar button.heading-smaller:after { - content: "▼"; -} - -.editor-toolbar.disabled-for-preview button:not(.no-disable) { - opacity: 0.6; - pointer-events: none; -} - -@media only screen and (max-width: 700px) { - .editor-toolbar i.no-mobile { - display: none; - } -} - -.editor-statusbar { - padding: 8px 10px; - font-size: 12px; - color: #959694; - text-align: right; -} - -.editor-statusbar span { - display: inline-block; - min-width: 4em; - margin-left: 1em; -} - -.editor-statusbar .lines:before { - content: "lines: "; -} - -.editor-statusbar .words:before { - content: "words: "; -} - -.editor-statusbar .characters:before { - content: "characters: "; -} - -.editor-preview-full { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 7; - overflow: auto; - display: none; - box-sizing: border-box; -} - -.editor-preview-side { - position: fixed; - bottom: 0; - width: 50%; - top: 50px; - right: 0; - z-index: 9; - overflow: auto; - display: none; - box-sizing: border-box; - border: 1px solid #ddd; - word-wrap: break-word; -} - -.editor-preview-active-side { - display: block; -} - -.editor-preview-active { - display: block; -} - -.editor-preview { - padding: 10px; - background: #fafafa; -} - -.editor-preview > p { - margin-top: 0; -} - -.editor-preview pre { - background: #eee; - margin-bottom: 10px; -} - -.editor-preview table td, -.editor-preview table th { - border: 1px solid #ddd; - padding: 5px; -} - -.cm-s-easymde .cm-tag { - color: #63a35c; -} - -.cm-s-easymde .cm-attribute { - color: #795da3; -} - -.cm-s-easymde .cm-string { - color: #183691; -} - -.cm-s-easymde .cm-header-1 { - font-size: 200%; - line-height: 200%; -} - -.cm-s-easymde .cm-header-2 { - font-size: 160%; - line-height: 160%; -} - -.cm-s-easymde .cm-header-3 { - font-size: 125%; - line-height: 125%; -} - -.cm-s-easymde .cm-header-4 { - font-size: 110%; - line-height: 110%; -} - -.cm-s-easymde .cm-comment { - background: rgba(0, 0, 0, 0.05); - border-radius: 2px; -} - -.cm-s-easymde .cm-link { - color: #7f8c8d; -} - -.cm-s-easymde .cm-url { - color: #aab2b3; -} - -.cm-s-easymde .cm-quote { - color: #7f8c8d; - font-style: italic; -} - -.editor-toolbar .easymde-dropdown { - position: relative; - background: linear-gradient( - to bottom right, - #fff 0%, - #fff 84%, - #333 50%, - #333 100% - ); - border-radius: 0; - border: 1px solid #fff; -} - -.editor-toolbar .easymde-dropdown:hover { - background: linear-gradient( - to bottom right, - #fff 0%, - #fff 84%, - #333 50%, - #333 100% - ); -} - -.easymde-dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); - padding: 8px; - z-index: 2; - top: 30px; -} - -.easymde-dropdown:active .easymde-dropdown-content, -.easymde-dropdown:focus .easymde-dropdown-content { - display: block; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/flag-icons.scss b/CTFd/plugins/UserChallengeManagement/assets/css/includes/flag-icons.scss deleted file mode 100644 index 0b8d791d3e..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/flag-icons.scss +++ /dev/null @@ -1,511 +0,0 @@ -$flags: ( - ad: "🇦🇩", - // Andorra - ae: "🇦🇪", - // United Arab Emirates - af: "🇦🇫", - // Afghanistan - ag: "🇦🇬", - // Antigua and Barbuda - ai: "🇦🇮", - // Anguilla - al: "🇦🇱", - // Albania - am: "🇦🇲", - // Armenia - ao: "🇦🇴", - // Angola - aq: "🇦🇶", - // Antarctica - ar: "🇦🇷", - // Argentina - as: "🇦🇸", - // American Samoa - at: "🇦🇹", - // Austria - au: "🇦🇺", - // Australia - aw: "🇦🇼", - // Aruba - ax: "🇦🇽", - // Åland Islands - az: "🇦🇿", - // Azerbaijan - ba: "🇧🇦", - // Bosnia and Herzegovina - bb: "🇧🇧", - // Barbados - bd: "🇧🇩", - // Bangladesh - be: "🇧🇪", - // Belgium - bf: "🇧🇫", - // Burkina Faso - bg: "🇧🇬", - // Bulgaria - bh: "🇧🇭", - // Bahrain - bi: "🇧🇮", - // Burundi - bj: "🇧🇯", - // Benin - bl: "🇧🇱", - // Saint Barthélemy - bm: "🇧🇲", - // Bermuda - bn: "🇧🇳", - // Brunei Darussalam - bo: "🇧🇴", - // Bolivia - bq: "🇧🇶", - // Bonaire, Sint Eustatius and Saba - br: "🇧🇷", - // Brazil - bs: "🇧🇸", - // Bahamas - bt: "🇧🇹", - // Bhutan - bv: "🇧🇻", - // Bouvet Island - bw: "🇧🇼", - // Botswana - by: "🇧🇾", - // Belarus - bz: "🇧🇿", - // Belize - ca: "🇨🇦", - // Canada - cc: "🇨🇨", - // Cocos (Keeling) Islands - cd: "🇨🇩", - // Congo - cf: "🇨🇫", - // Central African Republic - cg: "🇨🇬", - // Congo - ch: "🇨🇭", - // Switzerland - ci: "🇨🇮", - // Côte D'Ivoire - ck: "🇨🇰", - // Cook Islands - cl: "🇨🇱", - // Chile - cm: "🇨🇲", - // Cameroon - cn: "🇨🇳", - // China - co: "🇨🇴", - // Colombia - cr: "🇨🇷", - // Costa Rica - cu: "🇨🇺", - // Cuba - cv: "🇨🇻", - // Cape Verde - cw: "🇨🇼", - // Curaçao - cx: "🇨🇽", - // Christmas Island - cy: "🇨🇾", - // Cyprus - cz: "🇨🇿", - // Czech Republic - de: "🇩🇪", - // Germany - dj: "🇩🇯", - // Djibouti - dk: "🇩🇰", - // Denmark - dm: "🇩🇲", - // Dominica - do: "🇩🇴", - // Dominican Republic - dz: "🇩🇿", - // Algeria - ec: "🇪🇨", - // Ecuador - ee: "🇪🇪", - // Estonia - eg: "🇪🇬", - // Egypt - eh: "🇪🇭", - // Western Sahara - er: "🇪🇷", - // Eritrea - es: "🇪🇸", - // Spain - et: "🇪🇹", - // Ethiopia - fi: "🇫🇮", - // Finland - fj: "🇫🇯", - // Fiji - fk: "🇫🇰", - // Falkland Islands (Malvinas) - fm: "🇫🇲", - // Micronesia - fo: "🇫🇴", - // Faroe Islands - fr: "🇫🇷", - // France - ga: "🇬🇦", - // Gabon - gb: "🇬🇧", - // United Kingdom - gd: "🇬🇩", - // Grenada - ge: "🇬🇪", - // Georgia - gf: "🇬🇫", - // French Guiana - gg: "🇬🇬", - // Guernsey - gh: "🇬🇭", - // Ghana - gi: "🇬🇮", - // Gibraltar - gl: "🇬🇱", - // Greenland - gm: "🇬🇲", - // Gambia - gn: "🇬🇳", - // Guinea - gp: "🇬🇵", - // Guadeloupe - gq: "🇬🇶", - // Equatorial Guinea - gr: "🇬🇷", - // Greece - gs: "🇬🇸", - // South Georgia - gt: "🇬🇹", - // Guatemala - gu: "🇬🇺", - // Guam - gw: "🇬🇼", - // Guinea-Bissau - gy: "🇬🇾", - // Guyana - hk: "🇭🇰", - // Hong Kong - hm: "🇭🇲", - // Heard Island and Mcdonald Islands - hn: "🇭🇳", - // Honduras - hr: "🇭🇷", - // Croatia - ht: "🇭🇹", - // Haiti - hu: "🇭🇺", - // Hungary - id: "🇮🇩", - // Indonesia - ie: "🇮🇪", - // Ireland - il: "🇮🇱", - // Israel - im: "🇮🇲", - // Isle of Man - in: "🇮🇳", - // India - io: "🇮🇴", - // British Indian Ocean Territory - iq: "🇮🇶", - // Iraq - ir: "🇮🇷", - // Iran - is: "🇮🇸", - // Iceland - it: "🇮🇹", - // Italy - je: "🇯🇪", - // Jersey - jm: "🇯🇲", - // Jamaica - jo: "🇯🇴", - // Jordan - jp: "🇯🇵", - // Japan - ke: "🇰🇪", - // Kenya - kg: "🇰🇬", - // Kyrgyzstan - kh: "🇰🇭", - // Cambodia - ki: "🇰🇮", - // Kiribati - km: "🇰🇲", - // Comoros - kn: "🇰🇳", - // Saint Kitts and Nevis - kp: "🇰🇵", - // North Korea - kr: "🇰🇷", - // South Korea - kw: "🇰🇼", - // Kuwait - ky: "🇰🇾", - // Cayman Islands - kz: "🇰🇿", - // Kazakhstan - la: "🇱🇦", - // Lao People's Democratic Republic - lb: "🇱🇧", - // Lebanon - lc: "🇱🇨", - // Saint Lucia - li: "🇱🇮", - // Liechtenstein - lk: "🇱🇰", - // Sri Lanka - lr: "🇱🇷", - // Liberia - ls: "🇱🇸", - // Lesotho - lt: "🇱🇹", - // Lithuania - lu: "🇱🇺", - // Luxembourg - lv: "🇱🇻", - // Latvia - ly: "🇱🇾", - // Libya - ma: "🇲🇦", - // Morocco - mc: "🇲🇨", - // Monaco - md: "🇲🇩", - // Moldova - me: "🇲🇪", - // Montenegro - mf: "🇲🇫", - // Saint Martin (French Part) - mg: "🇲🇬", - // Madagascar - mh: "🇲🇭", - // Marshall Islands - mk: "🇲🇰", - // Macedonia - ml: "🇲🇱", - // Mali - mm: "🇲🇲", - // Myanmar - mn: "🇲🇳", - // Mongolia - mo: "🇲🇴", - // Macao - mp: "🇲🇵", - // Northern Mariana Islands - mq: "🇲🇶", - // Martinique - mr: "🇲🇷", - // Mauritania - ms: "🇲🇸", - // Montserrat - mt: "🇲🇹", - // Malta - mu: "🇲🇺", - // Mauritius - mv: "🇲🇻", - // Maldives - mw: "🇲🇼", - // Malawi - mx: "🇲🇽", - // Mexico - my: "🇲🇾", - // Malaysia - mz: "🇲🇿", - // Mozambique - na: "🇳🇦", - // Namibia - nc: "🇳🇨", - // New Caledonia - ne: "🇳🇪", - // Niger - nf: "🇳🇫", - // Norfolk Island - ng: "🇳🇬", - // Nigeria - ni: "🇳🇮", - // Nicaragua - nl: "🇳🇱", - // Netherlands - no: "🇳🇴", - // Norway - np: "🇳🇵", - // Nepal - nr: "🇳🇷", - // Nauru - nu: "🇳🇺", - // Niue - nz: "🇳🇿", - // New Zealand - om: "🇴🇲", - // Oman - pa: "🇵🇦", - // Panama - pe: "🇵🇪", - // Peru - pf: "🇵🇫", - // French Polynesia - pg: "🇵🇬", - // Papua New Guinea - ph: "🇵🇭", - // Philippines - pk: "🇵🇰", - // Pakistan - pl: "🇵🇱", - // Poland - pm: "🇵🇲", - // Saint Pierre and Miquelon - pn: "🇵🇳", - // Pitcairn - pr: "🇵🇷", - // Puerto Rico - ps: "🇵🇸", - // Palestinian Territory - pt: "🇵🇹", - // Portugal - pw: "🇵🇼", - // Palau - py: "🇵🇾", - // Paraguay - qa: "🇶🇦", - // Qatar - re: "🇷🇪", - // Réunion - ro: "🇷🇴", - // Romania - rs: "🇷🇸", - // Serbia - ru: "🇷🇺", - // Russia - rw: "🇷🇼", - // Rwanda - sa: "🇸🇦", - // Saudi Arabia - sb: "🇸🇧", - // Solomon Islands - sc: "🇸🇨", - // Seychelles - sd: "🇸🇩", - // Sudan - se: "🇸🇪", - // Sweden - sg: "🇸🇬", - // Singapore - sh: "🇸🇭", - // Saint Helena, Ascension and Tristan Da Cunha - si: "🇸🇮", - // Slovenia - sj: "🇸🇯", - // Svalbard and Jan Mayen - sk: "🇸🇰", - // Slovakia - sl: "🇸🇱", - // Sierra Leone - sm: "🇸🇲", - // San Marino - sn: "🇸🇳", - // Senegal - so: "🇸🇴", - // Somalia - sr: "🇸🇷", - // Suriname - ss: "🇸🇸", - // South Sudan - st: "🇸🇹", - // Sao Tome and Principe - sv: "🇸🇻", - // El Salvador - sx: "🇸🇽", - // Sint Maarten (Dutch Part) - sy: "🇸🇾", - // Syrian Arab Republic - sz: "🇸🇿", - // Swaziland - tc: "🇹🇨", - // Turks and Caicos Islands - td: "🇹🇩", - // Chad - tf: "🇹🇫", - // French Southern Territories - tg: "🇹🇬", - // Togo - th: "🇹🇭", - // Thailand - tj: "🇹🇯", - // Tajikistan - tk: "🇹🇰", - // Tokelau - tl: "🇹🇱", - // Timor-Leste - tm: "🇹🇲", - // Turkmenistan - tn: "🇹🇳", - // Tunisia - to: "🇹🇴", - // Tonga - tr: "🇹🇷", - // Turkey - tt: "🇹🇹", - // Trinidad and Tobago - tv: "🇹🇻", - // Tuvalu - tw: "🇹🇼", - // Taiwan - tz: "🇹🇿", - // Tanzania - ua: "🇺🇦", - // Ukraine - ug: "🇺🇬", - // Uganda - um: "🇺🇲", - // United States Minor Outlying Islands - us: "🇺🇸", - // United States - uy: "🇺🇾", - // Uruguay - uz: "🇺🇿", - // Uzbekistan - va: "🇻🇦", - // Vatican City - vc: "🇻🇨", - // Saint Vincent and The Grenadines - ve: "🇻🇪", - // Venezuela - vg: "🇻🇬", - // Virgin Islands, British - vi: "🇻🇮", - // Virgin Islands, U.S. - vn: "🇻🇳", - // Viet Nam - vu: "🇻🇺", - // Vanuatu - wf: "🇼🇫", - // Wallis and Futuna - ws: "🇼🇸", - // Samoa - ye: "🇾🇪", - // Yemen - yt: "🇾🇹", - // Mayotte - za: "🇿🇦", - // South Africa - zm: "🇿🇲", - // Zambia - zw: "🇿🇼", - // Zimbabwe -); - -[class^="flag-"] { - font-style: normal; -} - -// generate classes -@each $name, $icon in $flags { - .flag-#{$name}:before { - content: $icon; - } -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/jumbotron.css b/CTFd/plugins/UserChallengeManagement/assets/css/includes/jumbotron.css deleted file mode 100644 index b377b0c75b..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/jumbotron.css +++ /dev/null @@ -1,4 +0,0 @@ -/* Move down content because we have a fixed navbar that is 3.5rem tall */ -main { - padding-top: 3.5rem; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/min-height.scss b/CTFd/plugins/UserChallengeManagement/assets/css/includes/min-height.scss deleted file mode 100644 index 0741fb0a11..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/min-height.scss +++ /dev/null @@ -1,15 +0,0 @@ -.min-vh-0 { - min-height: 0vh !important; -} -.min-vh-25 { - min-height: 25vh !important; -} -.min-vh-50 { - min-height: 50vh !important; -} -.min-vh-75 { - min-height: 75vh !important; -} -.min-vh-100 { - min-height: 100vh !important; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/opacity.scss b/CTFd/plugins/UserChallengeManagement/assets/css/includes/opacity.scss deleted file mode 100644 index 7763e27440..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/opacity.scss +++ /dev/null @@ -1,15 +0,0 @@ -.opacity-0 { - opacity: 0 !important; -} -.opacity-25 { - opacity: 0.25 !important; -} -.opacity-50 { - opacity: 0.5 !important; -} -.opacity-75 { - opacity: 0.75 !important; -} -.opacity-100 { - opacity: 1 !important; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/includes/sticky-footer.css b/CTFd/plugins/UserChallengeManagement/assets/css/includes/sticky-footer.css deleted file mode 100644 index 940b9dcd79..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/includes/sticky-footer.css +++ /dev/null @@ -1,30 +0,0 @@ -/* Sticky footer styles --------------------------------------------------- */ -html { - position: relative; - min-height: 100%; -} - -body { - margin-bottom: 60px; /* Margin bottom by footer height */ -} - -.footer { - position: absolute; - - /* prevent scrollbars from showing on pages that don't use the full page height */ - bottom: 1px; - - width: 100%; - - /* Set the fixed height of the footer here */ - height: 60px; - - /* Override line-height from core because we have two lines in the admin panel */ - line-height: normal !important; - - /* Avoid covering things */ - z-index: -20; - - /*background-color: #f5f5f5;*/ -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/css/main.scss b/CTFd/plugins/UserChallengeManagement/assets/css/main.scss deleted file mode 100644 index fb7c669fbb..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/css/main.scss +++ /dev/null @@ -1,160 +0,0 @@ -@import "~/bootstrap/scss/bootstrap.scss"; -@import "includes/jumbotron.css"; -@import "includes/sticky-footer.css"; -@import "includes/award-icons.scss"; -@import "includes/flag-icons.scss"; -@import "includes/opacity.scss"; -@import "includes/min-height.scss"; - -html, -body, -.container { - font-family: "Lato", "LatoOffline", sans-serif; -} - -h1, -h2 { - font-family: "Raleway", "RalewayOffline", sans-serif; - font-weight: 500; - letter-spacing: 2px; -} - -a { - color: #337ab7; - text-decoration: none; -} - -table > thead > tr > td { - /* Remove border line from thead of all tables */ - /* It can overlap with other element styles */ - border-top: none !important; -} - -blockquote { - border-left: 4px solid $secondary; - padding-left: 15px; -} - -.table thead th { - white-space: nowrap; -} - -.fa-spin.spinner { - text-align: center; - opacity: 0.5; -} - -.spinner-error { - padding-top: 20vh; - text-align: center; - opacity: 0.5; -} - -.jumbotron { - border-radius: 0; - text-align: center; -} - -.form-control:focus { - background-color: transparent; - border-color: #a3d39c; - box-shadow: 0 0 0 0.1rem #a3d39c; - transition: - background-color 0.3s, - border-color 0.3s; -} - -.input-filled-valid { - background-color: transparent !important; - border-color: #a3d39c; - box-shadow: 0 0 0 0.1rem #a3d39c; - transition: - background-color 0.3s, - border-color 0.3s; -} - -.input-filled-invalid { - background-color: transparent !important; - border-color: #d46767; - box-shadow: 0 0 0 0.1rem #d46767; - transition: - background-color 0.3s, - border-color 0.3s; -} - -.btn-outlined.btn-theme { - background: none; - color: #545454; - border-color: #545454; - border: 3px solid; -} - -.btn-outlined { - border-radius: 0; - -webkit-transition: all 0.3s; - -moz-transition: all 0.3s; - transition: all 0.3s; -} - -.btn { - letter-spacing: 1px; - text-decoration: none; - -moz-user-select: none; - border-radius: 0; - cursor: pointer; - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - white-space: nowrap; - font-size: 14px; - line-height: 20px; - font-weight: 700; - padding: 8px 20px; -} - -.btn-info { - background-color: #5b7290 !important; - border-color: #5b7290 !important; -} - -.badge-info { - background-color: #5b7290 !important; -} - -.alert { - border-radius: 0 !important; - padding: 0.8em; -} - -.btn-fa { - cursor: pointer; -} - -.close { - cursor: pointer; -} - -.cursor-pointer { - cursor: pointer; -} - -.cursor-help { - cursor: help; -} - -.modal-content { - -webkit-border-radius: 0 !important; - -moz-border-radius: 0 !important; - border-radius: 0 !important; -} - -.fa-disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.badge-notification { - vertical-align: top; - margin-left: -1.5em; - font-size: 50%; -} diff --git a/CTFd/plugins/UserChallengeManagement/assets/js/challenge.js b/CTFd/plugins/UserChallengeManagement/assets/js/challenge.js deleted file mode 100644 index 18363d56f0..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/js/challenge.js +++ /dev/null @@ -1,200 +0,0 @@ -import $ from "jquery"; -import "../compat/json"; -import "../compat/format"; -import { ezToast, ezQuery } from "../compat/ezq"; -import { htmlEntities } from "@ctfdio/ctfd-js/utils/html"; -import CTFd from "../compat/CTFd"; -import nunjucks from "nunjucks"; - -function renderSubmissionResponse(response, cb) { - const result = response.data; - - const result_message = $("#result-message"); - const result_notification = $("#result-notification"); - const answer_input = $("#submission-input"); - result_notification.removeClass(); - result_message.text(result.message); - - if (result.status === "authentication_required") { - window.location = - CTFd.config.urlRoot + - "/login?next=" + - CTFd.config.urlRoot + - window.location.pathname + - window.location.hash; - return; - } else if (result.status === "incorrect") { - // Incorrect key - result_notification.addClass( - "alert alert-danger alert-dismissable text-center", - ); - result_notification.slideDown(); - - answer_input.removeClass("correct"); - answer_input.addClass("wrong"); - setTimeout(function () { - answer_input.removeClass("wrong"); - }, 3000); - } else if (result.status === "correct") { - // Challenge Solved - result_notification.addClass( - "alert alert-success alert-dismissable text-center", - ); - result_notification.slideDown(); - - $(".challenge-solves").text( - parseInt($(".challenge-solves").text().split(" ")[0]) + 1 + " Solves", - ); - - answer_input.val(""); - answer_input.removeClass("wrong"); - answer_input.addClass("correct"); - } else if (result.status === "already_solved") { - // Challenge already solved - result_notification.addClass( - "alert alert-info alert-dismissable text-center", - ); - result_notification.slideDown(); - - answer_input.addClass("correct"); - } else if (result.status === "paused") { - // CTF is paused - result_notification.addClass( - "alert alert-warning alert-dismissable text-center", - ); - result_notification.slideDown(); - } else if (result.status === "ratelimited") { - // Keys per minute too high - result_notification.addClass( - "alert alert-warning alert-dismissable text-center", - ); - result_notification.slideDown(); - - answer_input.addClass("too-fast"); - setTimeout(function () { - answer_input.removeClass("too-fast"); - }, 3000); - } - setTimeout(function () { - $(".alert").slideUp(); - $("#submit-key").removeClass("disabled-button"); - $("#submit-key").prop("disabled", false); - }, 3000); - - if (cb) { - cb(result); - } -} - -$(() => { - $(".preview-challenge").click(function (_event) { - window.challenge = new Object(); - $.get( - CTFd.config.urlRoot + "/api/v1/challenges/" + window.CHALLENGE_ID, - function (response) { - const challenge_data = response.data; - challenge_data["solves"] = null; - - $.getScript( - CTFd.config.urlRoot + challenge_data.type_data.scripts.view, - function () { - $.get( - CTFd.config.urlRoot + challenge_data.type_data.templates.view, - function (template_data) { - $("#challenge-window").empty(); - const template = nunjucks.compile(template_data); - window.challenge.data = challenge_data; - window.challenge.preRender(); - - challenge_data["description"] = window.challenge.render( - challenge_data["description"], - ); - challenge_data["script_root"] = CTFd.config.urlRoot; - - $("#challenge-window").append(template.render(challenge_data)); - - $(".nav-tabs a").click(function (event) { - event.preventDefault(); - $(this).tab("show"); - }); - - // Handle modal toggling - $("#challenge-window").on("hide.bs.modal", function (_event) { - $("#submission-input").removeClass("wrong"); - $("#submission-input").removeClass("correct"); - $("#incorrect-key").slideUp(); - $("#correct-key").slideUp(); - $("#already-solved").slideUp(); - $("#too-fast").slideUp(); - }); - - $("#submit-key").click(function (event) { - event.preventDefault(); - $("#submit-key").addClass("disabled-button"); - $("#submit-key").prop("disabled", true); - window.challenge.submit(function (data) { - renderSubmissionResponse(data); - }, true); - // Preview passed as true - }); - - $("#submission-input").keyup(function (event) { - if (event.keyCode == 13) { - $("#submit-key").click(); - } - }); - - window.challenge.postRender(); - window.location.replace( - window.location.href.split("#")[0] + "#preview", - ); - - $("#challenge-window").modal(); - }, - ); - }, - ); - }, - ); - }); - - $(".delete-challenge").click(function (_event) { - ezQuery({ - title: "Delete Challenge", - body: "Are you sure you want to delete {0}".format( - "" + htmlEntities(window.CHALLENGE_NAME) + "", - ), - success: function () { - CTFd.fetch("/api/v1/challenges/" + window.CHALLENGE_ID, { - method: "DELETE", - }).then(function (response) { - if (response.success) { - window.location = CTFd.config.urlRoot + "/admin/challenges"; - } - }); - }, - }); - }); - - $("#challenge-update-container > form").submit(function (event) { - event.preventDefault(); - const params = $(event.target).serializeJSON(true); - - CTFd.fetch("/api/v1/challenges/" + window.CHALLENGE_ID, { - method: "PATCH", - credentials: "same-origin", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify(params), - }).then(function (data) { - if (data.success) { - ezToast({ - title: "Success", - body: "Your challenge has been updated!", - }); - } - }); - }); -}); diff --git a/CTFd/plugins/UserChallengeManagement/assets/js/new.js b/CTFd/plugins/UserChallengeManagement/assets/js/new.js deleted file mode 100644 index 478bc091ea..0000000000 --- a/CTFd/plugins/UserChallengeManagement/assets/js/new.js +++ /dev/null @@ -1,81 +0,0 @@ -import CTFd from "../compat/CTFd"; -import nunjucks from "nunjucks"; -import $ from "jquery"; -import "../compat/json"; - -window.challenge = new Object(); - -function loadChalTemplate(challenge) { - $.getScript(CTFd.config.urlRoot + challenge.scripts.view, function () { - $.get( - CTFd.config.urlRoot + challenge.templates.create, - function (template_data) { - const template = nunjucks.compile(template_data); - $("#create-chal-entry-div").html( - template.render({ - nonce: CTFd.config.csrfNonce, - script_root: CTFd.config.urlRoot, - }), - ); - - $.getScript( - CTFd.config.urlRoot + challenge.scripts.create, - function () { - $("#create-chal-entry-div form").submit(function (event) { - event.preventDefault(); - const params = $("#create-chal-entry-div form").serializeJSON(); - CTFd.fetch("/api/v1/challenges", { - method: "POST", - credentials: "same-origin", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify(params), - }).then(function (response) { - if (response.success) { - window.location = - CTFd.config.urlRoot + - "/admin/challenges/" + - response.data.id; - } - }); - }); - }, - ); - }, - ); - }); -} - -$.get(CTFd.config.urlRoot + "/api/v1/challenges/types", function (response) { - $("#create-chals-select").empty(); - const data = response.data; - const chal_type_amt = Object.keys(data).length; - if (chal_type_amt > 1) { - const option = ""; - $("#create-chals-select").append(option); - for (const key in data) { - const challenge = data[key]; - const option = $("