mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 05:54:19 +01:00
General fixes and PEP8 enforcement (#258)
* Fixing index page links when you deploy on a subdirectory * Updating travis for pep8 * autopep8 with just formatting changes
This commit is contained in:
@@ -5,4 +5,5 @@ python:
|
||||
install:
|
||||
- pip install -r development.txt
|
||||
script:
|
||||
- pep8 --ignore E501,E712 CTFd/ tests/
|
||||
- nosetests
|
||||
|
||||
@@ -13,6 +13,7 @@ from CTFd import utils
|
||||
|
||||
__version__ = '1.0.2'
|
||||
|
||||
|
||||
class ThemeLoader(FileSystemLoader):
|
||||
def get_source(self, environment, template):
|
||||
if template.startswith('admin/'):
|
||||
@@ -34,21 +35,21 @@ def create_app(config='CTFd.config.Config'):
|
||||
if url.drivername == 'postgres':
|
||||
url.drivername = 'postgresql'
|
||||
|
||||
## Creates database if the database database does not exist
|
||||
# Creates database if the database database does not exist
|
||||
if not database_exists(url):
|
||||
create_database(url)
|
||||
|
||||
## Register database
|
||||
# Register database
|
||||
db.init_app(app)
|
||||
|
||||
## Register Flask-Migrate
|
||||
# Register Flask-Migrate
|
||||
migrate.init_app(app, db)
|
||||
|
||||
## This creates tables instead of db.create_all()
|
||||
## Allows migrations to happen properly
|
||||
# This creates tables instead of db.create_all()
|
||||
# Allows migrations to happen properly
|
||||
migrate_upgrade()
|
||||
|
||||
## Alembic sqlite support is lacking so we should just create_all anyway
|
||||
# Alembic sqlite support is lacking so we should just create_all anyway
|
||||
if url.drivername.startswith('sqlite'):
|
||||
db.create_all()
|
||||
|
||||
@@ -59,10 +60,10 @@ def create_app(config='CTFd.config.Config'):
|
||||
|
||||
version = utils.get_config('ctf_version')
|
||||
|
||||
if not version: ## Upgrading from an unversioned CTFd
|
||||
if not version: # Upgrading from an unversioned CTFd
|
||||
utils.set_config('ctf_version', __version__)
|
||||
|
||||
if version and (StrictVersion(version) < StrictVersion(__version__)): ## Upgrading from an older version of CTFd
|
||||
if version and (StrictVersion(version) < StrictVersion(__version__)): # Upgrading from an older version of CTFd
|
||||
print("/*\\ CTFd has updated and must update the database! /*\\")
|
||||
print("/*\\ Please backup your database before proceeding! /*\\")
|
||||
print("/*\\ CTFd maintainers are not responsible for any data loss! /*\\")
|
||||
|
||||
@@ -6,6 +6,7 @@ from CTFd import utils
|
||||
|
||||
admin_containers = Blueprint('admin_containers', __name__)
|
||||
|
||||
|
||||
@admin_containers.route('/admin/containers', methods=['GET'])
|
||||
@admins_only
|
||||
def list_container():
|
||||
|
||||
@@ -7,6 +7,7 @@ from CTFd import utils
|
||||
|
||||
admin_keys = Blueprint('admin_keys', __name__)
|
||||
|
||||
|
||||
@admin_keys.route('/admin/key_types', methods=['GET'])
|
||||
@admins_only
|
||||
def admin_key_types():
|
||||
@@ -16,6 +17,7 @@ def admin_key_types():
|
||||
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
@admin_keys.route('/admin/keys', defaults={'keyid': None}, methods=['POST', 'GET'])
|
||||
@admin_keys.route('/admin/keys/<int:keyid>', methods=['POST', 'GET'])
|
||||
@admins_only
|
||||
@@ -53,7 +55,6 @@ def admin_keys_view(keyid):
|
||||
return '1'
|
||||
|
||||
|
||||
|
||||
@admin_keys.route('/admin/keys/<int:keyid>/delete', methods=['POST'])
|
||||
@admins_only
|
||||
def admin_delete_keys(keyid):
|
||||
|
||||
@@ -6,6 +6,7 @@ from CTFd import utils
|
||||
|
||||
admin_pages = Blueprint('admin_pages', __name__)
|
||||
|
||||
|
||||
@admin_pages.route('/admin/css', methods=['GET', 'POST'])
|
||||
@admins_only
|
||||
def admin_css():
|
||||
|
||||
@@ -7,6 +7,7 @@ from CTFd import utils
|
||||
|
||||
admin_scoreboard = Blueprint('admin_scoreboard', __name__)
|
||||
|
||||
|
||||
@admin_scoreboard.route('/admin/scoreboard')
|
||||
@admins_only
|
||||
def admin_scoreboard_view():
|
||||
|
||||
@@ -6,11 +6,13 @@ from CTFd import utils
|
||||
|
||||
admin_statistics = Blueprint('admin_statistics', __name__)
|
||||
|
||||
|
||||
@admin_statistics.route('/admin/graphs')
|
||||
@admins_only
|
||||
def admin_graphs():
|
||||
return render_template('admin/graphs.html')
|
||||
|
||||
|
||||
@admin_statistics.route('/admin/graphs/<graph_type>')
|
||||
@admins_only
|
||||
def admin_graph(graph_type):
|
||||
@@ -31,6 +33,7 @@ def admin_graph(graph_type):
|
||||
json_data[name] = count
|
||||
return jsonify(json_data)
|
||||
|
||||
|
||||
@admin_statistics.route('/admin/statistics', methods=['GET'])
|
||||
@admins_only
|
||||
def admin_stats():
|
||||
@@ -66,6 +69,7 @@ def admin_stats():
|
||||
most_solved=most_solved,
|
||||
least_solved=least_solved)
|
||||
|
||||
|
||||
@admin_statistics.route('/admin/wrong_keys', defaults={'page': '1'}, methods=['GET'])
|
||||
@admin_statistics.route('/admin/wrong_keys/<int:page>', methods=['GET'])
|
||||
@admins_only
|
||||
|
||||
@@ -8,6 +8,7 @@ from CTFd import utils
|
||||
|
||||
admin_teams = Blueprint('admin_teams', __name__)
|
||||
|
||||
|
||||
@admin_teams.route('/admin/teams', defaults={'page': '1'})
|
||||
@admin_teams.route('/admin/teams/<int:page>')
|
||||
@admins_only
|
||||
@@ -225,6 +226,7 @@ def delete_wrong_key(keyid):
|
||||
db.session.close()
|
||||
return '1'
|
||||
|
||||
|
||||
@admin_teams.route('/admin/awards/<int:award_id>/delete', methods=['POST'])
|
||||
@admins_only
|
||||
def delete_award(award_id):
|
||||
@@ -234,6 +236,7 @@ def delete_award(award_id):
|
||||
db.session.close()
|
||||
return '1'
|
||||
|
||||
|
||||
@admin_teams.route('/admin/teams/<int:teamid>/awards', methods=['GET'])
|
||||
@admins_only
|
||||
def admin_awards(teamid):
|
||||
|
||||
@@ -14,6 +14,7 @@ from CTFd import utils
|
||||
|
||||
challenges = Blueprint('challenges', __name__)
|
||||
|
||||
|
||||
@challenges.route('/hints/<int:hintid>', methods=['GET', 'POST'])
|
||||
def hints_view(hintid):
|
||||
hint = Hints.query.filter_by(id=hintid).first_or_404()
|
||||
@@ -293,7 +294,7 @@ def chal(chalid):
|
||||
logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
|
||||
# return '0' # key was wrong
|
||||
if max_tries:
|
||||
attempts_left = max_tries - fails - 1 ## Off by one since fails has changed since it was gotten
|
||||
attempts_left = max_tries - fails - 1 # Off by one since fails has changed since it was gotten
|
||||
tries_str = 'tries'
|
||||
if attempts_left == 1:
|
||||
tries_str = 'try'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
##### GENERATE SECRET KEY #####
|
||||
''' GENERATE SECRET KEY '''
|
||||
|
||||
with open('.ctfd_secret_key', 'a+b') as secret:
|
||||
secret.seek(0) # Seek to beginning of file since a+ mode leaves you at the end and w+ deletes the file
|
||||
@@ -10,7 +10,8 @@ with open('.ctfd_secret_key', 'a+b') as secret:
|
||||
secret.write(key)
|
||||
secret.flush()
|
||||
|
||||
##### SERVER SETTINGS #####
|
||||
''' SERVER SETTINGS '''
|
||||
|
||||
|
||||
class Config(object):
|
||||
'''
|
||||
@@ -25,7 +26,6 @@ class Config(object):
|
||||
'''
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY') or key
|
||||
|
||||
|
||||
'''
|
||||
SQLALCHEMY_DATABASE_URI is the URI that specifies the username, password, hostname, port, and database of the server
|
||||
used to hold the CTFd database.
|
||||
@@ -34,52 +34,44 @@ class Config(object):
|
||||
'''
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///{}/ctfd.db'.format(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
'''
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS is automatically disabled to suppress warnings and save memory. You should only enable
|
||||
this if you need it.
|
||||
'''
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
|
||||
'''
|
||||
SESSION_TYPE is a configuration value used for Flask-Session. It is currently unused in CTFd.
|
||||
http://pythonhosted.org/Flask-Session/#configuration
|
||||
'''
|
||||
SESSION_TYPE = "filesystem"
|
||||
|
||||
|
||||
'''
|
||||
SESSION_FILE_DIR is a configuration value used for Flask-Session. It is currently unused in CTFd.
|
||||
http://pythonhosted.org/Flask-Session/#configuration
|
||||
'''
|
||||
SESSION_FILE_DIR = "/tmp/flask_session"
|
||||
|
||||
|
||||
'''
|
||||
SESSION_COOKIE_HTTPONLY controls if cookies should be set with the HttpOnly flag.
|
||||
'''
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
|
||||
|
||||
'''
|
||||
PERMANENT_SESSION_LIFETIME is the lifetime of a session.
|
||||
'''
|
||||
PERMANENT_SESSION_LIFETIME = 604800 # 7 days in seconds
|
||||
|
||||
|
||||
'''
|
||||
HOST specifies the hostname where the CTFd instance will exist. It is currently unused.
|
||||
'''
|
||||
HOST = ".ctfd.io"
|
||||
|
||||
|
||||
'''
|
||||
MAILFROM_ADDR is the email address that emails are sent from if not overridden in the configuration panel.
|
||||
'''
|
||||
MAILFROM_ADDR = "noreply@ctfd.io"
|
||||
|
||||
|
||||
'''
|
||||
UPLOAD_FOLDER is the location where files are uploaded.
|
||||
The default destination is the CTFd/uploads folder. If you need Amazon S3 files
|
||||
@@ -87,14 +79,12 @@ class Config(object):
|
||||
'''
|
||||
UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), 'uploads')
|
||||
|
||||
|
||||
'''
|
||||
TEMPLATES_AUTO_RELOAD specifies whether Flask should check for modifications to templates and
|
||||
reload them automatically
|
||||
'''
|
||||
TEMPLATES_AUTO_RELOAD = True
|
||||
|
||||
|
||||
'''
|
||||
TRUSTED_PROXIES defines a set of regular expressions used for finding a user's IP address if the CTFd instance
|
||||
is behind a proxy. If you are running a CTF and users are on the same network as you, you may choose to remove
|
||||
@@ -114,7 +104,6 @@ class Config(object):
|
||||
'^192\.168\.'
|
||||
]
|
||||
|
||||
|
||||
'''
|
||||
CACHE_TYPE specifies how CTFd should cache configuration values. If CACHE_TYPE is set to 'redis', CTFd will make use
|
||||
of the REDIS_URL specified in environment variables. You can also choose to hardcode the REDIS_URL here.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from CTFd.plugins.keys import get_key_class
|
||||
from CTFd.models import db, Keys
|
||||
|
||||
|
||||
class BaseChallenge(object):
|
||||
id = None
|
||||
name = None
|
||||
|
||||
|
||||
class CTFdStandardChallenge(BaseChallenge):
|
||||
id = 0
|
||||
name = "standard"
|
||||
@@ -22,6 +24,7 @@ CHALLENGE_CLASSES = {
|
||||
0: CTFdStandardChallenge
|
||||
}
|
||||
|
||||
|
||||
def get_chal_class(class_id):
|
||||
cls = CHALLENGE_CLASSES.get(class_id)
|
||||
if cls is None:
|
||||
|
||||
@@ -11,6 +11,7 @@ class BaseKey(object):
|
||||
def compare(self, saved, provided):
|
||||
return True
|
||||
|
||||
|
||||
class CTFdStaticKey(BaseKey):
|
||||
id = 0
|
||||
name = "static"
|
||||
|
||||
@@ -102,7 +102,6 @@ def topteams(count):
|
||||
solves = Solves.query.filter_by(teamid=team.teamid)
|
||||
awards = Awards.query.filter_by(teamid=team.teamid)
|
||||
|
||||
|
||||
freeze = utils.get_config('freeze')
|
||||
|
||||
if freeze:
|
||||
@@ -112,7 +111,6 @@ def topteams(count):
|
||||
solves = solves.all()
|
||||
awards = awards.all()
|
||||
|
||||
|
||||
json['scores'][team.name] = []
|
||||
for x in solves:
|
||||
json['scores'][team.name].append({
|
||||
|
||||
@@ -226,7 +226,6 @@ def is_scoreboard_frozen():
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def ctftime():
|
||||
""" Checks whether it's CTF time or not. """
|
||||
|
||||
@@ -669,7 +668,7 @@ def export_ctf(segments=None):
|
||||
]
|
||||
}
|
||||
|
||||
## Backup database
|
||||
# Backup database
|
||||
backup = io.BytesIO()
|
||||
backup_zip = zipfile.ZipFile(backup, 'w')
|
||||
|
||||
@@ -682,7 +681,7 @@ def export_ctf(segments=None):
|
||||
result_file.seek(0)
|
||||
backup_zip.writestr('db/{}.json'.format(item), result_file.read())
|
||||
|
||||
## Backup uploads
|
||||
# Backup uploads
|
||||
upload_folder = os.path.join(os.path.normpath(app.root_path), get_config('UPLOAD_FOLDER'))
|
||||
for root, dirs, files in os.walk(upload_folder):
|
||||
for file in files:
|
||||
@@ -730,7 +729,7 @@ def import_ctf(backup, segments=None, erase=False):
|
||||
]
|
||||
}
|
||||
|
||||
## Need special handling of metadata
|
||||
# Need special handling of metadata
|
||||
if 'metadata' in segments:
|
||||
meta = groups['metadata']
|
||||
segments.remove('metadata')
|
||||
@@ -741,7 +740,7 @@ def import_ctf(backup, segments=None, erase=False):
|
||||
path = "db/{}.json".format(item)
|
||||
data = backup.open(path).read()
|
||||
|
||||
## Some JSON files will be empty
|
||||
# Some JSON files will be empty
|
||||
if data:
|
||||
if item == 'config':
|
||||
saved = json.loads(data)
|
||||
@@ -776,7 +775,6 @@ def import_ctf(backup, segments=None, erase=False):
|
||||
db.session.add(container)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
for segment in segments:
|
||||
group = groups[segment]
|
||||
for item in group:
|
||||
@@ -791,20 +789,20 @@ def import_ctf(backup, segments=None, erase=False):
|
||||
else:
|
||||
continue
|
||||
|
||||
## Extracting files
|
||||
# Extracting files
|
||||
files = [f for f in backup.namelist() if f.startswith('uploads/')]
|
||||
upload_folder = app.config.get('UPLOAD_FOLDER')
|
||||
for f in files:
|
||||
filename = f.split(os.sep, 1)
|
||||
|
||||
if len(filename) < 2: ## just an empty uploads directory (e.g. uploads/)
|
||||
if len(filename) < 2: # just an empty uploads directory (e.g. uploads/)
|
||||
continue
|
||||
|
||||
filename = filename[1] ## Get the second entry in the list (the actual filename)
|
||||
filename = filename[1] # Get the second entry in the list (the actual filename)
|
||||
full_path = os.path.join(upload_folder, filename)
|
||||
dirname = os.path.dirname(full_path)
|
||||
|
||||
## Create any parent directories for the file
|
||||
# Create any parent directories for the file
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ def setup():
|
||||
|
||||
# Index page
|
||||
page = Pages('index', """<div class="container main-container">
|
||||
<img class="logo" src="{0}/static/original/img/logo.png" />
|
||||
<img class="logo" src="static/original/img/logo.png" />
|
||||
<h3 class="text-center">
|
||||
<p>A cool CTF platform from <a href="https://ctfd.io">ctfd.io</a></p>
|
||||
<p>Follow us on social media:</p>
|
||||
@@ -55,7 +55,7 @@ def setup():
|
||||
</h3>
|
||||
<br>
|
||||
<h4 class="text-center">
|
||||
<a href="{0}/admin">Click here</a> to login and setup your CTF
|
||||
<a href="admin">Click here</a> to login and setup your CTF
|
||||
</h4>
|
||||
</div>""".format(request.script_root))
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ coverage>=4.1
|
||||
mock>=2.0.0
|
||||
nose>=1.3.7
|
||||
rednose>=1.1.1
|
||||
pep8==1.7.0
|
||||
|
||||
@@ -106,6 +106,7 @@ def gen_solve(db, chalid, teamid, ip='127.0.0.1', flag='rightkey'):
|
||||
db.session.commit()
|
||||
return solve
|
||||
|
||||
|
||||
def gen_wrongkey(db, teamid, chalid, flag='wrongkey'):
|
||||
wrongkey = WrongKeys(teamid, chalid, flag)
|
||||
db.session.add(wrongkey)
|
||||
|
||||
@@ -22,7 +22,7 @@ def test_register_user():
|
||||
|
||||
|
||||
def test_register_duplicate_teamname():
|
||||
"""A user shouldn't be able to use and already registered team name"""
|
||||
"""A user shouldn't be able to use an already registered team name"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app, name="user1", email="user1@ctfd.io", password="password")
|
||||
@@ -74,7 +74,7 @@ def test_user_isnt_admin():
|
||||
|
||||
|
||||
def test_user_get_teams():
|
||||
"""Can a registered user can load /teams"""
|
||||
"""Can a registered user load /teams"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -84,7 +84,7 @@ def test_user_get_teams():
|
||||
|
||||
|
||||
def test_user_get_scoreboard():
|
||||
"""Can a registered user can load /scoreboard"""
|
||||
"""Can a registered user load /scoreboard"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -94,7 +94,7 @@ def test_user_get_scoreboard():
|
||||
|
||||
|
||||
def test_user_get_scores():
|
||||
"""Can a registered user can load /scores"""
|
||||
"""Can a registered user load /scores"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -104,7 +104,7 @@ def test_user_get_scores():
|
||||
|
||||
|
||||
def test_user_get_topteams():
|
||||
"""Can a registered user can load /top/10"""
|
||||
"""Can a registered user load /top/10"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -114,7 +114,7 @@ def test_user_get_topteams():
|
||||
|
||||
|
||||
def test_user_get_challenges():
|
||||
"""Can a registered user can load /challenges"""
|
||||
"""Can a registered user load /challenges"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -124,7 +124,7 @@ def test_user_get_challenges():
|
||||
|
||||
|
||||
def test_user_get_chals():
|
||||
"""Can a registered user can load /chals"""
|
||||
"""Can a registered user load /chals"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -134,7 +134,7 @@ def test_user_get_chals():
|
||||
|
||||
|
||||
def test_user_get_solves_per_chal():
|
||||
"""Can a registered user can load /chals/solves"""
|
||||
"""Can a registered user load /chals/solves"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -144,7 +144,7 @@ def test_user_get_solves_per_chal():
|
||||
|
||||
|
||||
def test_user_get_solves():
|
||||
"""Can a registered user can load /solves"""
|
||||
"""Can a registered user load /solves"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -154,7 +154,7 @@ def test_user_get_solves():
|
||||
|
||||
|
||||
def test_user_get_team_page():
|
||||
"""Can a registered user can load their public profile (/team/2)"""
|
||||
"""Can a registered user load their public profile (/team/2)"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
@@ -164,7 +164,7 @@ def test_user_get_team_page():
|
||||
|
||||
|
||||
def test_user_get_profile():
|
||||
"""Can a registered user can load their private profile (/profile)"""
|
||||
"""Can a registered user load their private profile (/profile)"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
register_user(app)
|
||||
|
||||
Reference in New Issue
Block a user