mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 05:54:19 +01:00
Plugins enhanced utils (#231)
* Updating utils functions to be monkey patchable * Also fixing a team email update issue * Adding more tests
This commit is contained in:
@@ -8,7 +8,8 @@ from sqlalchemy.exc import OperationalError, ProgrammingError
|
||||
from sqlalchemy_utils import database_exists, create_database
|
||||
from six.moves import input
|
||||
|
||||
from CTFd.utils import get_config, set_config, cache, migrate, migrate_upgrade, migrate_stamp
|
||||
from CTFd.utils import cache, migrate, migrate_upgrade, migrate_stamp
|
||||
from CTFd import utils
|
||||
|
||||
__version__ = '1.0.1'
|
||||
|
||||
@@ -16,7 +17,7 @@ class ThemeLoader(FileSystemLoader):
|
||||
def get_source(self, environment, template):
|
||||
if template.startswith('admin/'):
|
||||
return super(ThemeLoader, self).get_source(environment, template)
|
||||
theme = get_config('ctf_theme')
|
||||
theme = utils.get_config('ctf_theme')
|
||||
template = "/".join([theme, template])
|
||||
return super(ThemeLoader, self).get_source(environment, template)
|
||||
|
||||
@@ -53,10 +54,10 @@ def create_app(config='CTFd.config.Config'):
|
||||
cache.init_app(app)
|
||||
app.cache = cache
|
||||
|
||||
version = get_config('ctf_version')
|
||||
version = utils.get_config('ctf_version')
|
||||
|
||||
if not version: ## Upgrading from an unversioned CTFd
|
||||
set_config('ctf_version', __version__)
|
||||
utils.set_config('ctf_version', __version__)
|
||||
|
||||
if version and (StrictVersion(version) < StrictVersion(__version__)): ## Upgrading from an older version of CTFd
|
||||
print("/*\\ CTFd has updated and must update the database! /*\\")
|
||||
@@ -65,13 +66,13 @@ def create_app(config='CTFd.config.Config'):
|
||||
if input('Run database migrations (Y/N)').lower().strip() == 'y':
|
||||
migrate_stamp()
|
||||
migrate_upgrade()
|
||||
set_config('ctf_version', __version__)
|
||||
utils.set_config('ctf_version', __version__)
|
||||
else:
|
||||
print('/*\\ Ignored database migrations... /*\\')
|
||||
exit()
|
||||
|
||||
if not get_config('ctf_theme'):
|
||||
set_config('ctf_theme', 'original')
|
||||
if not utils.get_config('ctf_theme'):
|
||||
utils.set_config('ctf_theme', 'original')
|
||||
|
||||
from CTFd.views import views
|
||||
from CTFd.challenges import challenges
|
||||
|
||||
@@ -7,9 +7,7 @@ from flask import current_app as app, render_template, request, redirect, jsonif
|
||||
from passlib.hash import bcrypt_sha256
|
||||
from sqlalchemy.sql import not_
|
||||
|
||||
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, get_configurable_plugins
|
||||
from CTFd.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
from CTFd.scoreboard import get_standings
|
||||
from CTFd.plugins.keys import get_key_class, KEY_CLASSES
|
||||
@@ -22,6 +20,8 @@ from CTFd.admin.containers import admin_containers
|
||||
from CTFd.admin.keys import admin_keys
|
||||
from CTFd.admin.teams import admin_teams
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
|
||||
admin = Blueprint('admin', __name__)
|
||||
|
||||
@@ -38,13 +38,13 @@ def admin_view():
|
||||
@admins_only
|
||||
def admin_plugin_config(plugin):
|
||||
if request.method == 'GET':
|
||||
if plugin in get_configurable_plugins():
|
||||
if plugin in utils.get_configurable_plugins():
|
||||
config = open(os.path.join(app.root_path, 'plugins', plugin, 'config.html')).read()
|
||||
return render_template('admin/page.html', content=config)
|
||||
abort(404)
|
||||
elif request.method == 'POST':
|
||||
for k, v in request.form.items():
|
||||
set_config(k, v)
|
||||
utils.set_config(k, v)
|
||||
return '1'
|
||||
|
||||
|
||||
@@ -80,28 +80,28 @@ def admin_config():
|
||||
mail_tls = None
|
||||
mail_ssl = None
|
||||
finally:
|
||||
view_challenges_unregistered = set_config('view_challenges_unregistered', view_challenges_unregistered)
|
||||
view_scoreboard_if_authed = set_config('view_scoreboard_if_authed', view_scoreboard_if_authed)
|
||||
hide_scores = set_config('hide_scores', hide_scores)
|
||||
prevent_registration = set_config('prevent_registration', prevent_registration)
|
||||
prevent_name_change = set_config('prevent_name_change', prevent_name_change)
|
||||
view_after_ctf = set_config('view_after_ctf', view_after_ctf)
|
||||
verify_emails = set_config('verify_emails', verify_emails)
|
||||
mail_tls = set_config('mail_tls', mail_tls)
|
||||
mail_ssl = set_config('mail_ssl', mail_ssl)
|
||||
view_challenges_unregistered = utils.set_config('view_challenges_unregistered', view_challenges_unregistered)
|
||||
view_scoreboard_if_authed = utils.set_config('view_scoreboard_if_authed', view_scoreboard_if_authed)
|
||||
hide_scores = utils.set_config('hide_scores', hide_scores)
|
||||
prevent_registration = utils.set_config('prevent_registration', prevent_registration)
|
||||
prevent_name_change = utils.set_config('prevent_name_change', prevent_name_change)
|
||||
view_after_ctf = utils.set_config('view_after_ctf', view_after_ctf)
|
||||
verify_emails = utils.set_config('verify_emails', verify_emails)
|
||||
mail_tls = utils.set_config('mail_tls', mail_tls)
|
||||
mail_ssl = utils.set_config('mail_ssl', mail_ssl)
|
||||
|
||||
mail_server = set_config("mail_server", request.form.get('mail_server', None))
|
||||
mail_port = set_config("mail_port", request.form.get('mail_port', None))
|
||||
mail_server = utils.set_config("mail_server", request.form.get('mail_server', None))
|
||||
mail_port = utils.set_config("mail_port", request.form.get('mail_port', None))
|
||||
|
||||
mail_username = set_config("mail_username", request.form.get('mail_username', None))
|
||||
mail_password = set_config("mail_password", request.form.get('mail_password', None))
|
||||
mail_username = utils.set_config("mail_username", request.form.get('mail_username', None))
|
||||
mail_password = utils.set_config("mail_password", request.form.get('mail_password', None))
|
||||
|
||||
ctf_name = set_config("ctf_name", request.form.get('ctf_name', None))
|
||||
ctf_theme = set_config("ctf_theme", request.form.get('ctf_theme', None))
|
||||
ctf_name = utils.set_config("ctf_name", request.form.get('ctf_name', None))
|
||||
ctf_theme = utils.set_config("ctf_theme", request.form.get('ctf_theme', None))
|
||||
|
||||
mailfrom_addr = set_config("mailfrom_addr", request.form.get('mailfrom_addr', None))
|
||||
mg_base_url = set_config("mg_base_url", request.form.get('mg_base_url', None))
|
||||
mg_api_key = set_config("mg_api_key", request.form.get('mg_api_key', None))
|
||||
mailfrom_addr = utils.set_config("mailfrom_addr", request.form.get('mailfrom_addr', None))
|
||||
mg_base_url = utils.set_config("mg_base_url", request.form.get('mg_base_url', None))
|
||||
mg_api_key = utils.set_config("mg_api_key", request.form.get('mg_api_key', None))
|
||||
|
||||
db_start = Config.query.filter_by(key='start').first()
|
||||
db_start.value = start
|
||||
@@ -120,36 +120,36 @@ def admin_config():
|
||||
|
||||
with app.app_context():
|
||||
cache.clear()
|
||||
ctf_name = get_config('ctf_name')
|
||||
ctf_theme = get_config('ctf_theme')
|
||||
hide_scores = get_config('hide_scores')
|
||||
ctf_name = utils.get_config('ctf_name')
|
||||
ctf_theme = utils.get_config('ctf_theme')
|
||||
hide_scores = utils.get_config('hide_scores')
|
||||
|
||||
mail_server = get_config('mail_server')
|
||||
mail_port = get_config('mail_port')
|
||||
mail_username = get_config('mail_username')
|
||||
mail_password = get_config('mail_password')
|
||||
mail_server = utils.get_config('mail_server')
|
||||
mail_port = utils.get_config('mail_port')
|
||||
mail_username = utils.get_config('mail_username')
|
||||
mail_password = utils.get_config('mail_password')
|
||||
|
||||
mailfrom_addr = get_config('mailfrom_addr')
|
||||
mg_api_key = get_config('mg_api_key')
|
||||
mg_base_url = get_config('mg_base_url')
|
||||
mailfrom_addr = utils.get_config('mailfrom_addr')
|
||||
mg_api_key = utils.get_config('mg_api_key')
|
||||
mg_base_url = utils.get_config('mg_base_url')
|
||||
|
||||
view_after_ctf = get_config('view_after_ctf')
|
||||
start = get_config('start')
|
||||
end = get_config('end')
|
||||
view_after_ctf = utils.get_config('view_after_ctf')
|
||||
start = utils.get_config('start')
|
||||
end = utils.get_config('end')
|
||||
|
||||
mail_tls = get_config('mail_tls')
|
||||
mail_ssl = get_config('mail_ssl')
|
||||
mail_tls = utils.get_config('mail_tls')
|
||||
mail_ssl = utils.get_config('mail_ssl')
|
||||
|
||||
view_challenges_unregistered = get_config('view_challenges_unregistered')
|
||||
view_scoreboard_if_authed = get_config('view_scoreboard_if_authed')
|
||||
prevent_registration = get_config('prevent_registration')
|
||||
prevent_name_change = get_config('prevent_name_change')
|
||||
verify_emails = get_config('verify_emails')
|
||||
view_challenges_unregistered = utils.get_config('view_challenges_unregistered')
|
||||
view_scoreboard_if_authed = utils.get_config('view_scoreboard_if_authed')
|
||||
prevent_registration = utils.get_config('prevent_registration')
|
||||
prevent_name_change = utils.get_config('prevent_name_change')
|
||||
verify_emails = utils.get_config('verify_emails')
|
||||
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
||||
themes = get_themes()
|
||||
themes = utils.get_themes()
|
||||
themes.remove(ctf_theme)
|
||||
|
||||
return render_template('admin/config.html',
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
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
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
import os
|
||||
|
||||
admin_challenges = Blueprint('admin_challenges', __name__)
|
||||
@@ -109,7 +110,7 @@ def admin_files(chalid):
|
||||
files = request.files.getlist('files[]')
|
||||
|
||||
for f in files:
|
||||
upload_file(file=f, chalid=chalid)
|
||||
utils.upload_file(file=f, chalid=chalid)
|
||||
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
@@ -162,7 +163,7 @@ def admin_create_chal():
|
||||
db.session.commit()
|
||||
|
||||
for f in files:
|
||||
upload_file(file=f, chalid=chal.id)
|
||||
utils.upload_file(file=f, chalid=chal.id)
|
||||
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
@@ -183,7 +184,7 @@ def admin_delete_chal():
|
||||
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)
|
||||
utils.rmdir(folder)
|
||||
Tags.query.filter_by(chal=challenge.id).delete()
|
||||
Challenges.query.filter_by(id=challenge.id).delete()
|
||||
db.session.commit()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
admin_containers = Blueprint('admin_containers', __name__)
|
||||
|
||||
@admin_containers.route('/admin/containers', methods=['GET'])
|
||||
@@ -11,8 +11,8 @@ admin_containers = Blueprint('admin_containers', __name__)
|
||||
def list_container():
|
||||
containers = Containers.query.all()
|
||||
for c in containers:
|
||||
c.status = container_status(c.name)
|
||||
c.ports = ', '.join(container_ports(c.name, verbose=True))
|
||||
c.status = utils.container_status(c.name)
|
||||
c.ports = ', '.join(utils.container_ports(c.name, verbose=True))
|
||||
return render_template('admin/containers.html', containers=containers)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ def list_container():
|
||||
@admins_only
|
||||
def stop_container(container_id):
|
||||
container = Containers.query.filter_by(id=container_id).first_or_404()
|
||||
if container_stop(container.name):
|
||||
if utils.container_stop(container.name):
|
||||
return '1'
|
||||
else:
|
||||
return '0'
|
||||
@@ -30,13 +30,13 @@ def stop_container(container_id):
|
||||
@admins_only
|
||||
def run_container(container_id):
|
||||
container = Containers.query.filter_by(id=container_id).first_or_404()
|
||||
if container_status(container.name) == 'missing':
|
||||
if run_image(container.name):
|
||||
if utils.container_status(container.name) == 'missing':
|
||||
if utils.run_image(container.name):
|
||||
return '1'
|
||||
else:
|
||||
return '0'
|
||||
else:
|
||||
if container_start(container.name):
|
||||
if utils.container_start(container.name):
|
||||
return '1'
|
||||
else:
|
||||
return '0'
|
||||
@@ -46,7 +46,7 @@ def run_container(container_id):
|
||||
@admins_only
|
||||
def delete_container(container_id):
|
||||
container = Containers.query.filter_by(id=container_id).first_or_404()
|
||||
if delete_image(container.name):
|
||||
if utils.delete_image(container.name):
|
||||
db.session.delete(container)
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
@@ -61,6 +61,6 @@ def new_container():
|
||||
return redirect(url_for('admin_containers.list_container'))
|
||||
buildfile = request.form.get('buildfile')
|
||||
files = request.files.getlist('files[]')
|
||||
create_image(name=name, buildfile=buildfile, files=files)
|
||||
run_image(name)
|
||||
utils.create_image(name=name, buildfile=buildfile, files=files)
|
||||
utils.run_image(name)
|
||||
return redirect(url_for('admin_containers.list_container'))
|
||||
@@ -1,10 +1,10 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
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 import utils
|
||||
|
||||
admin_keys = Blueprint('admin_keys', __name__)
|
||||
|
||||
@admin_keys.route('/admin/key_types', methods=['GET'])
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
admin_pages = Blueprint('admin_pages', __name__)
|
||||
|
||||
@admin_pages.route('/admin/css', methods=['GET', 'POST'])
|
||||
@@ -11,7 +11,7 @@ admin_pages = Blueprint('admin_pages', __name__)
|
||||
def admin_css():
|
||||
if request.method == 'POST':
|
||||
css = request.form['css']
|
||||
css = set_config('css', css)
|
||||
css = utils.set_config('css', css)
|
||||
with app.app_context():
|
||||
cache.clear()
|
||||
return '1'
|
||||
@@ -49,7 +49,7 @@ def admin_pages_view(route):
|
||||
db.session.close()
|
||||
return redirect(url_for('admin_pages.admin_pages_view'))
|
||||
pages = Pages.query.all()
|
||||
return render_template('admin/pages.html', routes=pages, css=get_config('css'))
|
||||
return render_template('admin/pages.html', routes=pages, css=utils.get_config('css'))
|
||||
|
||||
|
||||
@admin_pages.route('/admin/page/<pageroute>/delete', methods=['POST'])
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
from CTFd.scoreboard import get_standings
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
admin_scoreboard = Blueprint('admin_scoreboard', __name__)
|
||||
|
||||
@admin_scoreboard.route('/admin/scoreboard')
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
admin_statistics = Blueprint('admin_statistics', __name__)
|
||||
|
||||
@admin_statistics.route('/admin/graphs')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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.utils import admins_only, is_admin, cache
|
||||
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
|
||||
from passlib.hash import bcrypt_sha256
|
||||
from sqlalchemy.sql import not_
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
admin_teams = Blueprint('admin_teams', __name__)
|
||||
|
||||
@admin_teams.route('/admin/teams', defaults={'page': '1'})
|
||||
@@ -84,7 +84,8 @@ def admin_team(teamid):
|
||||
return jsonify({'data': errors})
|
||||
else:
|
||||
user.name = name
|
||||
user.email = email
|
||||
if email:
|
||||
user.email = email
|
||||
if password:
|
||||
user.password = bcrypt_sha256.encrypt(password)
|
||||
user.website = website
|
||||
@@ -101,7 +102,7 @@ def email_user(teamid):
|
||||
message = request.form.get('msg', None)
|
||||
team = Teams.query.filter(Teams.id == teamid).first()
|
||||
if message and team:
|
||||
if sendmail(team.email, message):
|
||||
if utils.sendmail(team.email, message):
|
||||
return '1'
|
||||
return '0'
|
||||
|
||||
@@ -160,7 +161,7 @@ def admin_solves(teamid="all"):
|
||||
'team': x.teamid,
|
||||
'value': x.chal.value,
|
||||
'category': x.chal.category,
|
||||
'time': unix_time(x.date)
|
||||
'time': utils.unix_time(x.date)
|
||||
})
|
||||
for award in awards:
|
||||
json_data['solves'].append({
|
||||
@@ -169,7 +170,7 @@ def admin_solves(teamid="all"):
|
||||
'team': award.teamid,
|
||||
'value': award.value,
|
||||
'category': award.category or "Award",
|
||||
'time': unix_time(award.date)
|
||||
'time': utils.unix_time(award.date)
|
||||
})
|
||||
json_data['solves'].sort(key=lambda k: k['time'])
|
||||
return jsonify(json_data)
|
||||
|
||||
28
CTFd/auth.py
28
CTFd/auth.py
@@ -8,8 +8,8 @@ from flask import current_app as app, render_template, request, redirect, url_fo
|
||||
from itsdangerous import TimedSerializer, BadTimeSignature, Signer, BadSignature
|
||||
from passlib.hash import bcrypt_sha256
|
||||
|
||||
from CTFd.utils import sha512, is_safe_url, authed, can_send_mail, sendmail, can_register, get_config, verify_email
|
||||
from CTFd.models import db, Teams
|
||||
from CTFd import utils
|
||||
|
||||
auth = Blueprint('auth', __name__)
|
||||
|
||||
@@ -17,7 +17,7 @@ auth = Blueprint('auth', __name__)
|
||||
@auth.route('/confirm', methods=['POST', 'GET'])
|
||||
@auth.route('/confirm/<data>', methods=['GET'])
|
||||
def confirm_user(data=None):
|
||||
if not get_config('verify_emails'):
|
||||
if not utils.get_config('verify_emails'):
|
||||
return redirect(url_for('challenges.challenges_view'))
|
||||
if data and request.method == "GET": # User is confirming email account
|
||||
try:
|
||||
@@ -33,17 +33,17 @@ def confirm_user(data=None):
|
||||
logger = logging.getLogger('regs')
|
||||
logger.warn("[{0}] {1} confirmed {2}".format(time.strftime("%m/%d/%Y %X"), team.name.encode('utf-8'), team.email.encode('utf-8')))
|
||||
db.session.close()
|
||||
if authed():
|
||||
if utils.authed():
|
||||
return redirect(url_for('challenges.challenges_view'))
|
||||
return redirect(url_for('auth.login'))
|
||||
if not data and request.method == "GET": # User has been directed to the confirm page because his account is not verified
|
||||
if not authed():
|
||||
if not utils.authed():
|
||||
return redirect(url_for('auth.login'))
|
||||
team = Teams.query.filter_by(id=session['id']).first_or_404()
|
||||
if team.verified:
|
||||
return redirect(url_for('views.profile'))
|
||||
else:
|
||||
verify_email(team.email)
|
||||
utils.verify_email(team.email)
|
||||
return render_template('confirm.html', team=team)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ Did you initiate a password reset?
|
||||
|
||||
""".format(url_for('auth.reset_password', _external=True), urllib.quote_plus(token.encode('base64')))
|
||||
|
||||
sendmail(email, text)
|
||||
utils.sendmail(email, text)
|
||||
|
||||
return render_template('reset_password.html', errors=['If that account exists you will receive an email, please check your inbox'])
|
||||
return render_template('reset_password.html')
|
||||
@@ -88,7 +88,7 @@ Did you initiate a password reset?
|
||||
|
||||
@auth.route('/register', methods=['POST', 'GET'])
|
||||
def register():
|
||||
if not can_register():
|
||||
if not utils.can_register():
|
||||
return redirect(url_for('auth.login'))
|
||||
if request.method == 'POST':
|
||||
errors = []
|
||||
@@ -128,9 +128,9 @@ def register():
|
||||
session['username'] = team.name
|
||||
session['id'] = team.id
|
||||
session['admin'] = team.admin
|
||||
session['nonce'] = sha512(os.urandom(10))
|
||||
session['nonce'] = utils.sha512(os.urandom(10))
|
||||
|
||||
if can_send_mail() and get_config('verify_emails'): # Confirming users is enabled and we can send email.
|
||||
if utils.can_send_mail() and utils.get_config('verify_emails'): # Confirming users is enabled and we can send email.
|
||||
db.session.close()
|
||||
logger = logging.getLogger('regs')
|
||||
logger.warn("[{0}] {1} registered (UNCONFIRMED) with {2}".format(time.strftime("%m/%d/%Y %X"),
|
||||
@@ -138,8 +138,8 @@ def register():
|
||||
request.form['email'].encode('utf-8')))
|
||||
return redirect(url_for('auth.confirm_user'))
|
||||
else: # Don't care about confirming users
|
||||
if can_send_mail(): # We want to notify the user that they have registered.
|
||||
sendmail(request.form['email'], "You've successfully registered for {}".format(get_config('ctf_name')))
|
||||
if utils.can_send_mail(): # We want to notify the user that they have registered.
|
||||
utils.sendmail(request.form['email'], "You've successfully registered for {}".format(utils.get_config('ctf_name')))
|
||||
|
||||
db.session.close()
|
||||
|
||||
@@ -165,13 +165,13 @@ def login():
|
||||
session['username'] = team.name
|
||||
session['id'] = team.id
|
||||
session['admin'] = team.admin
|
||||
session['nonce'] = sha512(os.urandom(10))
|
||||
session['nonce'] = utils.sha512(os.urandom(10))
|
||||
db.session.close()
|
||||
|
||||
logger = logging.getLogger('logins')
|
||||
logger.warn("[{0}] {1} logged in".format(time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8')))
|
||||
|
||||
if request.args.get('next') and is_safe_url(request.args.get('next')):
|
||||
if request.args.get('next') and utils.is_safe_url(request.args.get('next')):
|
||||
return redirect(request.args.get('next'))
|
||||
return redirect(url_for('challenges.challenges_view'))
|
||||
else: # This user exists but the password is wrong
|
||||
@@ -189,6 +189,6 @@ def login():
|
||||
|
||||
@auth.route('/logout')
|
||||
def logout():
|
||||
if authed():
|
||||
if utils.authed():
|
||||
session.clear()
|
||||
return redirect(url_for('views.static_html'))
|
||||
|
||||
@@ -6,37 +6,38 @@ import time
|
||||
from flask import render_template, request, redirect, jsonify, url_for, session, Blueprint
|
||||
from sqlalchemy.sql import or_
|
||||
|
||||
from CTFd.utils import ctftime, view_after_ctf, authed, unix_time, get_kpm, user_can_view_challenges, is_admin, get_config, get_ip, is_verified, ctf_started, ctf_ended, ctf_name, hide_scores
|
||||
from CTFd.models import db, Challenges, Files, Solves, WrongKeys, Keys, Tags, Teams, Awards
|
||||
from CTFd.plugins.keys import get_key_class
|
||||
from CTFd.plugins.challenges import get_chal_class
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
challenges = Blueprint('challenges', __name__)
|
||||
|
||||
|
||||
@challenges.route('/challenges', methods=['GET'])
|
||||
def challenges_view():
|
||||
errors = []
|
||||
start = get_config('start') or 0
|
||||
end = get_config('end') or 0
|
||||
if not is_admin(): # User is not an admin
|
||||
if not ctftime():
|
||||
start = utils.get_config('start') or 0
|
||||
end = utils.get_config('end') or 0
|
||||
if not utils.is_admin(): # User is not an admin
|
||||
if not utils.ctftime():
|
||||
# It is not CTF time
|
||||
if view_after_ctf(): # But we are allowed to view after the CTF ends
|
||||
if utils.view_after_ctf(): # But we are allowed to view after the CTF ends
|
||||
pass
|
||||
else: # We are NOT allowed to view after the CTF ends
|
||||
if get_config('start') and not ctf_started():
|
||||
errors.append('{} has not started yet'.format(ctf_name()))
|
||||
if (get_config('end') and ctf_ended()) and not view_after_ctf():
|
||||
errors.append('{} has ended'.format(ctf_name()))
|
||||
if utils.get_config('start') and not utils.ctf_started():
|
||||
errors.append('{} has not started yet'.format(utils.ctf_name()))
|
||||
if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf():
|
||||
errors.append('{} has ended'.format(utils.ctf_name()))
|
||||
return render_template('chals.html', errors=errors, start=int(start), end=int(end))
|
||||
if get_config('verify_emails') and not is_verified(): # User is not confirmed
|
||||
if utils.get_config('verify_emails') and not utils.is_verified(): # User is not confirmed
|
||||
return redirect(url_for('auth.confirm_user'))
|
||||
if user_can_view_challenges(): # Do we allow unauthenticated users?
|
||||
if get_config('start') and not ctf_started():
|
||||
errors.append('{} has not started yet'.format(ctf_name()))
|
||||
if (get_config('end') and ctf_ended()) and not view_after_ctf():
|
||||
errors.append('{} has ended'.format(ctf_name()))
|
||||
if utils.user_can_view_challenges(): # Do we allow unauthenticated users?
|
||||
if utils.get_config('start') and not utils.ctf_started():
|
||||
errors.append('{} has not started yet'.format(utils.ctf_name()))
|
||||
if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf():
|
||||
errors.append('{} has ended'.format(utils.ctf_name()))
|
||||
return render_template('chals.html', errors=errors, start=int(start), end=int(end))
|
||||
else:
|
||||
return redirect(url_for('auth.login', next='challenges'))
|
||||
@@ -44,13 +45,13 @@ def challenges_view():
|
||||
|
||||
@challenges.route('/chals', methods=['GET'])
|
||||
def chals():
|
||||
if not is_admin():
|
||||
if not ctftime():
|
||||
if view_after_ctf():
|
||||
if not utils.is_admin():
|
||||
if not utils.ctftime():
|
||||
if utils.view_after_ctf():
|
||||
pass
|
||||
else:
|
||||
return redirect(url_for('views.static_html'))
|
||||
if user_can_view_challenges() and (ctf_started() or is_admin()):
|
||||
if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()):
|
||||
chals = Challenges.query.filter(or_(Challenges.hidden != True, Challenges.hidden == None)).order_by(Challenges.value).all()
|
||||
json = {'game': []}
|
||||
for x in chals:
|
||||
@@ -77,14 +78,14 @@ def chals():
|
||||
|
||||
@challenges.route('/chals/solves')
|
||||
def solves_per_chal():
|
||||
if not user_can_view_challenges():
|
||||
if not utils.user_can_view_challenges():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
|
||||
solves_sub = db.session.query(Solves.chalid, db.func.count(Solves.chalid).label('solves')).join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).group_by(Solves.chalid).subquery()
|
||||
solves = db.session.query(solves_sub.columns.chalid, solves_sub.columns.solves, Challenges.name) \
|
||||
.join(Challenges, solves_sub.columns.chalid == Challenges.id).all()
|
||||
json = {}
|
||||
if hide_scores():
|
||||
if utils.hide_scores():
|
||||
for chal, count, name in solves:
|
||||
json[chal] = -1
|
||||
else:
|
||||
@@ -100,10 +101,10 @@ def solves(teamid=None):
|
||||
solves = None
|
||||
awards = None
|
||||
if teamid is None:
|
||||
if is_admin():
|
||||
if utils.is_admin():
|
||||
solves = Solves.query.filter_by(teamid=session['id']).all()
|
||||
elif user_can_view_challenges():
|
||||
if authed():
|
||||
elif utils.user_can_view_challenges():
|
||||
if utils.authed():
|
||||
solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid == session['id'], Teams.banned == False).all()
|
||||
else:
|
||||
return jsonify({'solves': []})
|
||||
@@ -121,7 +122,7 @@ def solves(teamid=None):
|
||||
'team': solve.teamid,
|
||||
'value': solve.chal.value,
|
||||
'category': solve.chal.category,
|
||||
'time': unix_time(solve.date)
|
||||
'time': utils.unix_time(solve.date)
|
||||
})
|
||||
if awards:
|
||||
for award in awards:
|
||||
@@ -131,7 +132,7 @@ def solves(teamid=None):
|
||||
'team': award.teamid,
|
||||
'value': award.value,
|
||||
'category': award.category or "Award",
|
||||
'time': unix_time(award.date)
|
||||
'time': utils.unix_time(award.date)
|
||||
})
|
||||
json['solves'].sort(key=lambda k: k['time'])
|
||||
return jsonify(json)
|
||||
@@ -139,13 +140,13 @@ def solves(teamid=None):
|
||||
|
||||
@challenges.route('/maxattempts')
|
||||
def attempts():
|
||||
if not user_can_view_challenges():
|
||||
if not utils.user_can_view_challenges():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
chals = Challenges.query.add_columns('id').all()
|
||||
json = {'maxattempts': []}
|
||||
for chal, chalid in chals:
|
||||
fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count()
|
||||
if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
|
||||
if fails >= int(utils.get_config("max_tries")) and int(utils.get_config("max_tries")) > 0:
|
||||
json['maxattempts'].append({'chalid': chalid})
|
||||
return jsonify(json)
|
||||
|
||||
@@ -161,11 +162,11 @@ def fails(teamid):
|
||||
|
||||
@challenges.route('/chal/<int:chalid>/solves', methods=['GET'])
|
||||
def who_solved(chalid):
|
||||
if not user_can_view_challenges():
|
||||
if not utils.user_can_view_challenges():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
|
||||
json = {'teams': []}
|
||||
if hide_scores():
|
||||
if utils.hide_scores():
|
||||
return jsonify(json)
|
||||
solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.chalid == chalid, Teams.banned == False).order_by(Solves.date.asc())
|
||||
for solve in solves:
|
||||
@@ -175,19 +176,19 @@ def who_solved(chalid):
|
||||
|
||||
@challenges.route('/chal/<int:chalid>', methods=['POST'])
|
||||
def chal(chalid):
|
||||
if ctf_ended() and not view_after_ctf():
|
||||
if utils.ctf_ended() and not utils.view_after_ctf():
|
||||
return redirect(url_for('challenges.challenges_view'))
|
||||
if not user_can_view_challenges():
|
||||
if not utils.user_can_view_challenges():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
if authed() and is_verified() and (ctf_started() or view_after_ctf()):
|
||||
if utils.authed() and utils.is_verified() and (utils.ctf_started() or utils.view_after_ctf()):
|
||||
fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count()
|
||||
logger = logging.getLogger('keys')
|
||||
data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
|
||||
data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), utils.get_kpm(session['id']))
|
||||
print("[{0}] {1} submitted {2} with kpm {3}".format(*data))
|
||||
|
||||
# Anti-bruteforce / submitting keys too quickly
|
||||
if get_kpm(session['id']) > 10:
|
||||
if ctftime():
|
||||
if utils.get_kpm(session['id']) > 10:
|
||||
if utils.ctftime():
|
||||
wrong = WrongKeys(session['id'], chalid, request.form['key'])
|
||||
db.session.add(wrong)
|
||||
db.session.commit()
|
||||
@@ -214,15 +215,15 @@ def chal(chalid):
|
||||
|
||||
chal_class = get_chal_class(chal.type)
|
||||
if chal_class.solve(chal, provided_key):
|
||||
if ctftime():
|
||||
solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=provided_key)
|
||||
if utils.ctftime():
|
||||
solve = Solves(chalid=chalid, teamid=session['id'], ip=utils.get_ip(), flag=provided_key)
|
||||
db.session.add(solve)
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
|
||||
return jsonify({'status': '1', 'message': 'Correct'})
|
||||
|
||||
if ctftime():
|
||||
if utils.ctftime():
|
||||
wrong = WrongKeys(teamid=session['id'], chalid=chalid, flag=provided_key)
|
||||
db.session.add(wrong)
|
||||
db.session.commit()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from flask import render_template, jsonify, Blueprint, redirect, url_for, request
|
||||
from sqlalchemy.sql.expression import union_all
|
||||
|
||||
from CTFd.utils import unix_time, authed, get_config, hide_scores
|
||||
from CTFd.models import db, Teams, Solves, Awards, Challenges
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
scoreboard = Blueprint('scoreboard', __name__)
|
||||
|
||||
|
||||
@@ -35,9 +36,9 @@ def get_standings(admin=False, count=None):
|
||||
|
||||
@scoreboard.route('/scoreboard')
|
||||
def scoreboard_view():
|
||||
if get_config('view_scoreboard_if_authed') and not authed():
|
||||
if utils.get_config('view_scoreboard_if_authed') and not utils.authed():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
if hide_scores():
|
||||
if utils.hide_scores():
|
||||
return render_template('scoreboard.html', errors=['Scores are currently hidden'])
|
||||
standings = get_standings()
|
||||
return render_template('scoreboard.html', teams=standings)
|
||||
@@ -46,9 +47,9 @@ def scoreboard_view():
|
||||
@scoreboard.route('/scores')
|
||||
def scores():
|
||||
json = {'standings': []}
|
||||
if get_config('view_scoreboard_if_authed') and not authed():
|
||||
if utils.get_config('view_scoreboard_if_authed') and not utils.authed():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
if hide_scores():
|
||||
if utils.hide_scores():
|
||||
return jsonify(json)
|
||||
|
||||
standings = get_standings()
|
||||
@@ -61,9 +62,9 @@ def scores():
|
||||
@scoreboard.route('/top/<int:count>')
|
||||
def topteams(count):
|
||||
json = {'scores': {}}
|
||||
if get_config('view_scoreboard_if_authed') and not authed():
|
||||
if utils.get_config('view_scoreboard_if_authed') and not utils.authed():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
if hide_scores():
|
||||
if utils.hide_scores():
|
||||
return jsonify(json)
|
||||
|
||||
if count > 20 or count < 0:
|
||||
@@ -80,14 +81,14 @@ def topteams(count):
|
||||
'chal': x.chalid,
|
||||
'team': x.teamid,
|
||||
'value': x.chal.value,
|
||||
'time': unix_time(x.date)
|
||||
'time': utils.unix_time(x.date)
|
||||
})
|
||||
for award in awards:
|
||||
json['scores'][team.name].append({
|
||||
'chal': None,
|
||||
'team': award.teamid,
|
||||
'value': award.value,
|
||||
'time': unix_time(award.date)
|
||||
'time': utils.unix_time(award.date)
|
||||
})
|
||||
json['scores'][team.name] = sorted(json['scores'][team.name], key=lambda k: k['time'])
|
||||
return jsonify(json)
|
||||
|
||||
@@ -198,8 +198,10 @@ $('#update-user').click(function(e){
|
||||
console.log($.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'])
|
||||
console.log(row.find('.team-name > a'))
|
||||
row.find('.team-name > a').text( $.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'] );
|
||||
row.find('.team-email').text( $.grep(user_data, function(e){ return e.name == 'email'; })[0]['value'] );
|
||||
|
||||
var new_email = $.grep(user_data, function(e){ return e.name == 'email'; })[0]['value'];
|
||||
if (new_email){
|
||||
row.find('.team-email').text( new_email );
|
||||
}
|
||||
row.find('.team-website > a').empty()
|
||||
var website = $.grep(user_data, function(e){ return e.name == 'website'; })[0]['value']
|
||||
row.find('.team-website').append($('<a>').attr('href', website).text(website));
|
||||
|
||||
@@ -5,9 +5,9 @@ from flask import current_app as app, render_template, request, redirect, abort,
|
||||
from jinja2.exceptions import TemplateNotFound
|
||||
from passlib.hash import bcrypt_sha256
|
||||
|
||||
from CTFd.utils import authed, is_setup, validate_url, get_config, set_config, sha512, cache, ctftime, view_after_ctf, ctf_started, \
|
||||
is_admin, hide_scores
|
||||
from CTFd.models import db, Teams, Solves, Awards, Files, Pages
|
||||
from CTFd.utils import cache
|
||||
from CTFd import utils
|
||||
|
||||
views = Blueprint('views', __name__)
|
||||
|
||||
@@ -16,7 +16,7 @@ views = Blueprint('views', __name__)
|
||||
def redirect_setup():
|
||||
if request.path.startswith("/static"):
|
||||
return
|
||||
if not is_setup() and request.path != "/setup":
|
||||
if not utils.is_setup() and request.path != "/setup":
|
||||
return redirect(url_for('views.setup'))
|
||||
|
||||
|
||||
@@ -25,15 +25,15 @@ def setup():
|
||||
# with app.app_context():
|
||||
# admin = Teams.query.filter_by(admin=True).first()
|
||||
|
||||
if not is_setup():
|
||||
if not utils.is_setup():
|
||||
if not session.get('nonce'):
|
||||
session['nonce'] = sha512(os.urandom(10))
|
||||
session['nonce'] = utils.sha512(os.urandom(10))
|
||||
if request.method == 'POST':
|
||||
ctf_name = request.form['ctf_name']
|
||||
ctf_name = set_config('ctf_name', ctf_name)
|
||||
ctf_name = utils.set_config('ctf_name', ctf_name)
|
||||
|
||||
# CSS
|
||||
css = set_config('start', '')
|
||||
css = utils.set_config('start', '')
|
||||
|
||||
# Admin user
|
||||
name = request.form['name']
|
||||
@@ -56,29 +56,29 @@ def setup():
|
||||
</div>""".format(request.script_root))
|
||||
|
||||
# max attempts per challenge
|
||||
max_tries = set_config("max_tries", 0)
|
||||
max_tries = utils.set_config("max_tries", 0)
|
||||
|
||||
# Start time
|
||||
start = set_config('start', None)
|
||||
end = set_config('end', None)
|
||||
start = utils.set_config('start', None)
|
||||
end = utils.set_config('end', None)
|
||||
|
||||
# Challenges cannot be viewed by unregistered users
|
||||
view_challenges_unregistered = set_config('view_challenges_unregistered', None)
|
||||
view_challenges_unregistered = utils.set_config('view_challenges_unregistered', None)
|
||||
|
||||
# Allow/Disallow registration
|
||||
prevent_registration = set_config('prevent_registration', None)
|
||||
prevent_registration = utils.set_config('prevent_registration', None)
|
||||
|
||||
# Verify emails
|
||||
verify_emails = set_config('verify_emails', None)
|
||||
verify_emails = utils.set_config('verify_emails', None)
|
||||
|
||||
mail_server = set_config('mail_server', None)
|
||||
mail_port = set_config('mail_port', None)
|
||||
mail_tls = set_config('mail_tls', None)
|
||||
mail_ssl = set_config('mail_ssl', None)
|
||||
mail_username = set_config('mail_username', None)
|
||||
mail_password = set_config('mail_password', None)
|
||||
mail_server = utils.set_config('mail_server', None)
|
||||
mail_port = utils.set_config('mail_port', None)
|
||||
mail_tls = utils.set_config('mail_tls', None)
|
||||
mail_ssl = utils.set_config('mail_ssl', None)
|
||||
mail_username = utils.set_config('mail_username', None)
|
||||
mail_password = utils.set_config('mail_password', None)
|
||||
|
||||
setup = set_config('setup', True)
|
||||
setup = utils.set_config('setup', True)
|
||||
|
||||
db.session.add(page)
|
||||
db.session.add(admin)
|
||||
@@ -87,7 +87,7 @@ def setup():
|
||||
session['username'] = admin.name
|
||||
session['id'] = admin.id
|
||||
session['admin'] = admin.admin
|
||||
session['nonce'] = sha512(os.urandom(10))
|
||||
session['nonce'] = utils.sha512(os.urandom(10))
|
||||
|
||||
db.session.close()
|
||||
app.setup = False
|
||||
@@ -102,7 +102,7 @@ def setup():
|
||||
# Custom CSS handler
|
||||
@views.route('/static/user.css')
|
||||
def custom_css():
|
||||
return Response(get_config("css"), mimetype='text/css')
|
||||
return Response(utils.get_config("css"), mimetype='text/css')
|
||||
|
||||
|
||||
# Static HTML files
|
||||
@@ -124,7 +124,7 @@ def teams(page):
|
||||
page_start = results_per_page * (page - 1)
|
||||
page_end = results_per_page * (page - 1) + results_per_page
|
||||
|
||||
if get_config('verify_emails'):
|
||||
if utils.get_config('verify_emails'):
|
||||
count = Teams.query.filter_by(verified=True, banned=False).count()
|
||||
teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()
|
||||
else:
|
||||
@@ -136,7 +136,7 @@ def teams(page):
|
||||
|
||||
@views.route('/team/<int:teamid>', methods=['GET', 'POST'])
|
||||
def team(teamid):
|
||||
if get_config('view_scoreboard_if_authed') and not authed():
|
||||
if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():
|
||||
return redirect(url_for('auth.login', next=request.path))
|
||||
errors = []
|
||||
user = Teams.query.filter_by(id=teamid).first_or_404()
|
||||
@@ -146,7 +146,7 @@ def team(teamid):
|
||||
place = user.place()
|
||||
db.session.close()
|
||||
|
||||
if hide_scores() and teamid != session.get('id'):
|
||||
if utils.hide_scores() and teamid != session.get('id'):
|
||||
errors.append('Scores are currently hidden')
|
||||
|
||||
if errors:
|
||||
@@ -163,7 +163,7 @@ def team(teamid):
|
||||
|
||||
@views.route('/profile', methods=['POST', 'GET'])
|
||||
def profile():
|
||||
if authed():
|
||||
if utils.authed():
|
||||
if request.method == "POST":
|
||||
errors = []
|
||||
|
||||
@@ -175,7 +175,7 @@ def profile():
|
||||
|
||||
user = Teams.query.filter_by(id=session['id']).first()
|
||||
|
||||
if not get_config('prevent_name_change'):
|
||||
if not utils.get_config('prevent_name_change'):
|
||||
names = Teams.query.filter_by(name=name).first()
|
||||
name_len = len(request.form['name']) == 0
|
||||
|
||||
@@ -187,13 +187,13 @@ def profile():
|
||||
errors.append("Your old password doesn't match what we have.")
|
||||
if not valid_email:
|
||||
errors.append("That email doesn't look right")
|
||||
if not get_config('prevent_name_change') and names and name != session['username']:
|
||||
if not utils.get_config('prevent_name_change') and names and name != session['username']:
|
||||
errors.append('That team name is already taken')
|
||||
if emails and emails.id != session['id']:
|
||||
errors.append('That email has already been used')
|
||||
if not get_config('prevent_name_change') and name_len:
|
||||
if not utils.get_config('prevent_name_change') and name_len:
|
||||
errors.append('Pick a longer team name')
|
||||
if website.strip() and not validate_url(website):
|
||||
if website.strip() and not utils.validate_url(website):
|
||||
errors.append("That doesn't look like a valid URL")
|
||||
|
||||
if len(errors) > 0:
|
||||
@@ -201,11 +201,11 @@ def profile():
|
||||
affiliation=affiliation, country=country, errors=errors)
|
||||
else:
|
||||
team = Teams.query.filter_by(id=session['id']).first()
|
||||
if not get_config('prevent_name_change'):
|
||||
if not utils.get_config('prevent_name_change'):
|
||||
team.name = name
|
||||
if team.email != email.lower():
|
||||
team.email = email.lower()
|
||||
if get_config('verify_emails'):
|
||||
if utils.get_config('verify_emails'):
|
||||
team.verified = False
|
||||
session['username'] = team.name
|
||||
|
||||
@@ -224,8 +224,8 @@ def profile():
|
||||
website = user.website
|
||||
affiliation = user.affiliation
|
||||
country = user.country
|
||||
prevent_name_change = get_config('prevent_name_change')
|
||||
confirm_email = get_config('verify_emails') and not user.verified
|
||||
prevent_name_change = utils.get_config('prevent_name_change')
|
||||
confirm_email = utils.get_config('verify_emails') and not user.verified
|
||||
return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation,
|
||||
country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)
|
||||
else:
|
||||
@@ -237,9 +237,9 @@ def profile():
|
||||
def file_handler(path):
|
||||
f = Files.query.filter_by(location=path).first_or_404()
|
||||
if f.chal:
|
||||
if not is_admin():
|
||||
if not ctftime():
|
||||
if view_after_ctf() and ctf_started():
|
||||
if not utils.is_admin():
|
||||
if not utils.ctftime():
|
||||
if utils.view_after_ctf() and utils.ctf_started():
|
||||
pass
|
||||
else:
|
||||
abort(403)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from CTFd import create_app
|
||||
from CTFd.models import *
|
||||
from sqlalchemy_utils import database_exists, create_database, drop_database
|
||||
from sqlalchemy.engine.url import make_url
|
||||
|
||||
@@ -58,3 +59,62 @@ def login_as_user(app, name="user", password="password"):
|
||||
}
|
||||
client.post('/login', data=data)
|
||||
return client
|
||||
|
||||
|
||||
def gen_challenge(db, name='chal_name', description='chal_description', value=100, category='chal_category', type=0):
|
||||
chal = Challenges(name, description, value, category)
|
||||
db.session.add(chal)
|
||||
db.session.commit()
|
||||
return chal
|
||||
|
||||
|
||||
def gen_award(db, teamid, name="award_name", value=100):
|
||||
award = Awards(teamid, name, value)
|
||||
db.session.add(award)
|
||||
db.session.commit()
|
||||
return award
|
||||
|
||||
|
||||
def gen_tag(db, chal, tag='tag_tag'):
|
||||
tag = Tags(chal, tag)
|
||||
db.session.add(tag)
|
||||
db.session.commit()
|
||||
return tag
|
||||
|
||||
|
||||
def gen_file():
|
||||
pass
|
||||
|
||||
|
||||
def gen_key(db, chal, flag='flag', key_type=0):
|
||||
key = Keys(chal, flag, key_type)
|
||||
db.session.add(key)
|
||||
db.session.commit()
|
||||
return key
|
||||
|
||||
|
||||
def gen_team(db, name='name', email='user@ctfd.io', password='password'):
|
||||
team = Teams(name, email, password)
|
||||
db.session.add(team)
|
||||
db.session.commit()
|
||||
return team
|
||||
|
||||
|
||||
def gen_solve(db, chalid, teamid, ip='127.0.0.1', flag='rightkey'):
|
||||
solve = Solves(chalid, teamid, ip, flag)
|
||||
db.session.add(solve)
|
||||
db.session.commit()
|
||||
return solve
|
||||
|
||||
def gen_wrongkey(db, teamid, chalid, flag='wrongkey'):
|
||||
wrongkey = WrongKeys(teamid, chalid, flag)
|
||||
db.session.add(wrongkey)
|
||||
db.session.commit()
|
||||
return wrongkey
|
||||
|
||||
|
||||
def gen_tracking(db, ip, team):
|
||||
tracking = Tracking(ip, team)
|
||||
db.session.add(tracking)
|
||||
db.session.commit()
|
||||
return tracking
|
||||
@@ -0,0 +1,76 @@
|
||||
from tests.helpers import create_ctfd, register_user, login_as_user
|
||||
from CTFd.models import Teams
|
||||
|
||||
|
||||
def test_admin_panel():
|
||||
"""Does the admin panel return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin')
|
||||
assert r.status_code == 302
|
||||
r = client.get('/admin/graphs')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_pages():
|
||||
"""Does admin pages return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/pages')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_teams():
|
||||
"""Does admin teams return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/teams')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_scoreboard():
|
||||
"""Does admin scoreboard return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/scoreboard')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_containers():
|
||||
"""Does admin containers return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/containers')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_chals():
|
||||
"""Does admin chals return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/chals')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_statistics():
|
||||
"""Does admin statistics return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/statistics')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_admin_config():
|
||||
"""Does admin config return a 200 by default"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
client = login_as_user(app, name="admin", password="password")
|
||||
r = client.get('/admin/config')
|
||||
assert r.status_code == 200
|
||||
@@ -1,5 +1,6 @@
|
||||
from tests.helpers import create_ctfd, register_user, login_as_user
|
||||
from tests.helpers import create_ctfd, register_user, login_as_user, gen_challenge
|
||||
from CTFd.models import Teams
|
||||
import json
|
||||
|
||||
|
||||
def test_index():
|
||||
@@ -192,3 +193,15 @@ def test_user_get_reset_password():
|
||||
client = app.test_client()
|
||||
r = client.get('/reset_password')
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_viewing_challenges():
|
||||
"""Test that users can see added challenges"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
client = login_as_user(app)
|
||||
gen_challenge(app.db)
|
||||
r = client.get('/chals')
|
||||
chals = json.loads(r.data)
|
||||
assert len(chals['game']) == 1
|
||||
Reference in New Issue
Block a user