mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 22:14:25 +01:00
207 lines
7.7 KiB
Python
207 lines
7.7 KiB
Python
from flask import current_app as app, render_template, request, redirect, jsonify, url_for, Blueprint
|
|
from CTFd.utils import admins_only, is_admin, unix_time, get_config, \
|
|
set_config, sendmail, rmdir, create_image, delete_image, run_image, container_status, container_ports, \
|
|
container_stop, container_start, get_themes, cache, upload_file
|
|
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
|
from CTFd.plugins.keys import get_key_class, KEY_CLASSES
|
|
from CTFd.plugins.challenges import get_chal_class, CHALLENGE_CLASSES
|
|
import os
|
|
|
|
admin_challenges = Blueprint('admin_challenges', __name__)
|
|
|
|
|
|
@admin_challenges.route('/admin/chal_types', methods=['GET'])
|
|
@admins_only
|
|
def admin_chal_types():
|
|
data = {}
|
|
for class_id in CHALLENGE_CLASSES:
|
|
data[class_id] = CHALLENGE_CLASSES.get(class_id).name
|
|
|
|
return jsonify(data)
|
|
|
|
|
|
@admin_challenges.route('/admin/chals', methods=['POST', 'GET'])
|
|
@admins_only
|
|
def admin_chals():
|
|
if request.method == 'POST':
|
|
chals = Challenges.query.add_columns('id', 'name', 'value', 'description', 'category', 'hidden', 'max_attempts').order_by(Challenges.value).all()
|
|
|
|
teams_with_points = db.session.query(Solves.teamid).join(Teams).filter(
|
|
Teams.banned == False).group_by(Solves.teamid).count()
|
|
|
|
json_data = {'game': []}
|
|
for x in chals:
|
|
solve_count = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(
|
|
Solves.chalid == x[1], Teams.banned == False).count()
|
|
if teams_with_points > 0:
|
|
percentage = (float(solve_count) / float(teams_with_points))
|
|
else:
|
|
percentage = 0.0
|
|
|
|
json_data['game'].append({
|
|
'id': x.id,
|
|
'name': x.name,
|
|
'value': x.value,
|
|
'description': x.description,
|
|
'category': x.category,
|
|
'hidden': x.hidden,
|
|
'max_attempts': x.max_attempts,
|
|
'percentage_solved': percentage
|
|
})
|
|
|
|
db.session.close()
|
|
return jsonify(json_data)
|
|
else:
|
|
return render_template('admin/chals.html')
|
|
|
|
|
|
@admin_challenges.route('/admin/tags/<int:chalid>', methods=['GET', 'POST'])
|
|
@admins_only
|
|
def admin_tags(chalid):
|
|
if request.method == 'GET':
|
|
tags = Tags.query.filter_by(chal=chalid).all()
|
|
json_data = {'tags': []}
|
|
for x in tags:
|
|
json_data['tags'].append({'id': x.id, 'chal': x.chal, 'tag': x.tag})
|
|
return jsonify(json_data)
|
|
|
|
elif request.method == 'POST':
|
|
newtags = request.form.getlist('tags[]')
|
|
for x in newtags:
|
|
tag = Tags(chalid, x)
|
|
db.session.add(tag)
|
|
db.session.commit()
|
|
db.session.close()
|
|
return '1'
|
|
|
|
|
|
@admin_challenges.route('/admin/tags/<int:tagid>/delete', methods=['POST'])
|
|
@admins_only
|
|
def admin_delete_tags(tagid):
|
|
if request.method == 'POST':
|
|
tag = Tags.query.filter_by(id=tagid).first_or_404()
|
|
db.session.delete(tag)
|
|
db.session.commit()
|
|
db.session.close()
|
|
return '1'
|
|
|
|
|
|
@admin_challenges.route('/admin/files/<int:chalid>', methods=['GET', 'POST'])
|
|
@admins_only
|
|
def admin_files(chalid):
|
|
if request.method == 'GET':
|
|
files = Files.query.filter_by(chal=chalid).all()
|
|
json_data = {'files': []}
|
|
for x in files:
|
|
json_data['files'].append({'id': x.id, 'file': x.location})
|
|
return jsonify(json_data)
|
|
if request.method == 'POST':
|
|
if request.form['method'] == "delete":
|
|
f = Files.query.filter_by(id=request.form['file']).first_or_404()
|
|
upload_folder = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
|
|
if os.path.exists(os.path.join(upload_folder, f.location)): # Some kind of os.path.isfile issue on Windows...
|
|
os.unlink(os.path.join(upload_folder, f.location))
|
|
db.session.delete(f)
|
|
db.session.commit()
|
|
db.session.close()
|
|
return '1'
|
|
elif request.form['method'] == "upload":
|
|
files = request.files.getlist('files[]')
|
|
|
|
for f in files:
|
|
upload_file(file=f, chalid=chalid)
|
|
|
|
db.session.commit()
|
|
db.session.close()
|
|
return '1'
|
|
|
|
|
|
@admin_challenges.route('/admin/chal/<int:chalid>/<prop>', methods=['GET'])
|
|
@admins_only
|
|
def admin_get_values(chalid, prop):
|
|
challenge = Challenges.query.filter_by(id=chalid).first_or_404()
|
|
if prop == 'keys':
|
|
chal_keys = Keys.query.filter_by(chal=challenge.id).all()
|
|
json_data = {'keys': []}
|
|
for x in chal_keys:
|
|
json_data['keys'].append({'id': x.id, 'key': x.flag, 'type': x.key_type, 'type_name': get_key_class(x.key_type).name})
|
|
return jsonify(json_data)
|
|
elif prop == 'tags':
|
|
tags = Tags.query.filter_by(chal=chalid).all()
|
|
json_data = {'tags': []}
|
|
for x in tags:
|
|
json_data['tags'].append({'id': x.id, 'chal': x.chal, 'tag': x.tag})
|
|
return jsonify(json_data)
|
|
|
|
|
|
@admin_challenges.route('/admin/chal/new', methods=['GET', 'POST'])
|
|
@admins_only
|
|
def admin_create_chal():
|
|
if request.method == 'POST':
|
|
files = request.files.getlist('files[]')
|
|
|
|
# Create challenge
|
|
chal = Challenges(request.form['name'], request.form['desc'], request.form['value'], request.form['category'], int(request.form['chaltype']))
|
|
if 'hidden' in request.form:
|
|
chal.hidden = True
|
|
else:
|
|
chal.hidden = False
|
|
|
|
max_attempts = request.form.get('max_attempts')
|
|
if max_attempts and max_attempts.isdigit():
|
|
chal.max_attempts = int(max_attempts)
|
|
|
|
db.session.add(chal)
|
|
db.session.flush()
|
|
|
|
flag = Keys(chal.id, request.form['key'], int(request.form['key_type[0]']))
|
|
if request.form.get('keydata'):
|
|
flag.data = request.form.get('keydata')
|
|
db.session.add(flag)
|
|
|
|
db.session.commit()
|
|
|
|
for f in files:
|
|
upload_file(file=f, chalid=chal.id)
|
|
|
|
db.session.commit()
|
|
db.session.close()
|
|
return redirect(url_for('admin_challenges.admin_chals'))
|
|
else:
|
|
return render_template('admin/chals/create.html')
|
|
|
|
|
|
@admin_challenges.route('/admin/chal/delete', methods=['POST'])
|
|
@admins_only
|
|
def admin_delete_chal():
|
|
challenge = Challenges.query.filter_by(id=request.form['id']).first_or_404()
|
|
WrongKeys.query.filter_by(chalid=challenge.id).delete()
|
|
Solves.query.filter_by(chalid=challenge.id).delete()
|
|
Keys.query.filter_by(chal=challenge.id).delete()
|
|
files = Files.query.filter_by(chal=challenge.id).all()
|
|
Files.query.filter_by(chal=challenge.id).delete()
|
|
for file in files:
|
|
upload_folder = app.config['UPLOAD_FOLDER']
|
|
folder = os.path.dirname(os.path.join(os.path.normpath(app.root_path), upload_folder, file.location))
|
|
rmdir(folder)
|
|
Tags.query.filter_by(chal=challenge.id).delete()
|
|
Challenges.query.filter_by(id=challenge.id).delete()
|
|
db.session.commit()
|
|
db.session.close()
|
|
return '1'
|
|
|
|
|
|
@admin_challenges.route('/admin/chal/update', methods=['POST'])
|
|
@admins_only
|
|
def admin_update_chal():
|
|
challenge = Challenges.query.filter_by(id=request.form['id']).first_or_404()
|
|
challenge.name = request.form['name']
|
|
challenge.description = request.form['desc']
|
|
challenge.value = int(request.form.get('value', 0)) if request.form.get('value', 0) else 0
|
|
challenge.max_attempts = int(request.form.get('max_attempts', 0)) if request.form.get('max_attempts', 0) else 0
|
|
challenge.category = request.form['category']
|
|
challenge.hidden = 'hidden' in request.form
|
|
db.session.add(challenge)
|
|
db.session.commit()
|
|
db.session.close()
|
|
return redirect(url_for('admin_challenges.admin_chals')) |