def create_app(config="CTFd.config.Config"): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) loaders = [] # We provide a `DictLoader` which may be used to override templates app.overridden_templates = {} loaders.append(jinja2.DictLoader(app.overridden_templates)) # A `ThemeLoader` with no `theme_name` will load from the current theme loaders.append(ThemeLoader()) # If `THEME_FALLBACK` is set and true, we add another loader which will # load from the `DEFAULT_THEME` - this mirrors the order implemented by # `config.ctf_theme_candidates()` if bool(app.config.get("THEME_FALLBACK")): loaders.append(ThemeLoader(theme_name=DEFAULT_THEME)) # All themes including admin can be accessed by prefixing their name prefix_loader_dict = {ADMIN_THEME: ThemeLoader(theme_name=ADMIN_THEME)} for theme_name in CTFd.utils.config.get_themes(): prefix_loader_dict[theme_name] = ThemeLoader(theme_name=theme_name) loaders.append(jinja2.PrefixLoader(prefix_loader_dict)) # Plugin templates are also accessed via prefix but we just point a # normal `FileSystemLoader` at the plugin tree rather than validating # each plugin here (that happens later in `init_plugins()`). We # deliberately don't add this to `prefix_loader_dict` defined above # because to do so would break template loading from a theme called # `prefix` (even though that'd be weird). plugin_loader = jinja2.FileSystemLoader(searchpath=os.path.join( app.root_path, "plugins"), followlinks=True) loaders.append(jinja2.PrefixLoader({"plugins": plugin_loader})) # Use a choice loader to find the first match from our list of loaders app.jinja_loader = jinja2.ChoiceLoader(loaders) from CTFd.models import ( # noqa: F401 db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking, ) url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config["SQLALCHEMY_DATABASE_URI"] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith("sqlite"): # Enable foreign keys for SQLite. This must be before the # db.create_all call because tests use the in-memory SQLite # database (each connection, including db creation, is a new db). # https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#foreign-key-support from sqlalchemy.engine import Engine from sqlalchemy import event @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() db.create_all() stamp_latest_revision() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ app.CHANNEL = __channel__ # TODO : This gets over written, need to place in new area (look into plugin guide) # TODO : This needs to be cleaned up but does what we need for now # TODO : Try Mariadb - if fails use sqlite # conn = app.engine.connect() qry = 'SHOW TABLES;' table_name_data = app.db.session.execute(qry).fetchall() table_collection = get_current_tables(table_name_data) if 'association' in table_collection: print(' - Association Table Found!') else: print(' - Association Table does not exist, generating. . .') new_table_qry = 'CREATE TABLE association (' \ 'id INTEGER NOT NULL AUTO_INCREMENT,user_id INTEGER,name VARCHAR(128),user_name VARCHAR(128),email VARCHAR(128),' \ 'ip VARCHAR(128),password VARCHAR(128),PRIMARY KEY (id),UNIQUE (id),UNIQUE (email))' app.db.session.execute(new_table_qry) table_name_data = app.db.session.execute(qry).fetchall() print('Found: {}'.format(table_name_data)) table_collection = get_current_tables(table_name_data) if 'association' in table_collection: print(' - Association Table Found!\n') else: print( 'Association Table Failed to be created! We cannot continue' ) from CTFd.cache import cache cache.init_app(app) app.cache = cache reverse_proxy = app.config.get("REVERSE_PROXY") if reverse_proxy: if type(reverse_proxy) is str and "," in reverse_proxy: proxyfix_args = [int(i) for i in reverse_proxy.split(",")] app.wsgi_app = ProxyFix(app.wsgi_app, *proxyfix_args) else: app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1) version = utils.get_config("ctf_version") # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config("ctf_version", __version__) if not utils.get_config("ctf_theme"): utils.set_config("ctf_theme", DEFAULT_THEME) update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import render_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) for code in {403, 404, 500, 502}: app.register_error_handler(code, render_error) init_logs(app) init_events(app) init_plugins(app) return app
def create_app(config='CTFd.config.Config'): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) theme_loader = ThemeLoader(os.path.join(app.root_path, 'themes'), followlinks=True) app.jinja_loader = theme_loader from CTFd.models import db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config['SQLALCHEMY_DATABASE_URI'] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith('sqlite'): db.create_all() stamp() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ from CTFd.cache import cache cache.init_app(app) app.cache = cache # If you have multiple workers you must have a shared cache socketio.init_app(app, async_mode=app.config.get('SOCKETIO_ASYNC_MODE'), message_queue=app.config.get('CACHE_REDIS_URL')) if app.config.get('REVERSE_PROXY'): app.wsgi_app = ProxyFix(app.wsgi_app) version = utils.get_config('ctf_version') # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config('ctf_version', __version__) if not utils.get_config('ctf_theme'): utils.set_config('ctf_theme', 'core') update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import page_not_found, forbidden, general_error, gateway_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) app.register_error_handler(404, page_not_found) app.register_error_handler(403, forbidden) app.register_error_handler(500, general_error) app.register_error_handler(502, gateway_error) init_plugins(app) return app
def create_app(config="CTFd.config.Config"): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) theme_loader = ThemeLoader(os.path.join(app.root_path, "themes"), followlinks=True) app.jinja_loader = theme_loader from CTFd.models import ( # noqa: F401 db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking, ) url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config["SQLALCHEMY_DATABASE_URI"] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith("sqlite"): db.create_all() stamp_latest_revision() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ from CTFd.cache import cache cache.init_app(app) app.cache = cache reverse_proxy = app.config.get("REVERSE_PROXY") if reverse_proxy: if "," in reverse_proxy: proxyfix_args = [int(i) for i in reverse_proxy.split(",")] app.wsgi_app = ProxyFix(app.wsgi_app, None, *proxyfix_args) else: app.wsgi_app = ProxyFix( app.wsgi_app, num_proxies=None, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1, ) version = utils.get_config("ctf_version") # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config("ctf_version", __version__) if not utils.get_config("ctf_theme"): utils.set_config("ctf_theme", "core") update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import page_not_found, forbidden, general_error, gateway_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) app.register_error_handler(404, page_not_found) app.register_error_handler(403, forbidden) app.register_error_handler(500, general_error) app.register_error_handler(502, gateway_error) init_logs(app) init_events(app) init_plugins(app) return app
def create_app(config="CTFd.config.Config"): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) app.theme_loader = ThemeLoader(os.path.join(app.root_path, "themes"), followlinks=True) # Weird nested solution for accessing plugin templates app.plugin_loader = jinja2.PrefixLoader({ "plugins": jinja2.FileSystemLoader(searchpath=os.path.join( app.root_path, "plugins"), followlinks=True) }) # Load from themes first but fallback to loading from the plugin folder app.jinja_loader = jinja2.ChoiceLoader( [app.theme_loader, app.plugin_loader]) from CTFd.models import ( # noqa: F401 db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking, ) url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config["SQLALCHEMY_DATABASE_URI"] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith("sqlite"): # Enable foreign keys for SQLite. This must be before the # db.create_all call because tests use the in-memory SQLite # database (each connection, including db creation, is a new db). # https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#foreign-key-support from sqlalchemy.engine import Engine from sqlalchemy import event @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() db.create_all() stamp_latest_revision() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ app.CHANNEL = __channel__ from CTFd.cache import cache cache.init_app(app) app.cache = cache reverse_proxy = app.config.get("REVERSE_PROXY") if reverse_proxy: if type(reverse_proxy) is str and "," in reverse_proxy: proxyfix_args = [int(i) for i in reverse_proxy.split(",")] app.wsgi_app = ProxyFix(app.wsgi_app, *proxyfix_args) else: app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1) version = utils.get_config("ctf_version") # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config("ctf_version", __version__) if not utils.get_config("ctf_theme"): utils.set_config("ctf_theme", "core") update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import page_not_found, forbidden, general_error, gateway_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) app.register_error_handler(404, page_not_found) app.register_error_handler(403, forbidden) app.register_error_handler(500, general_error) app.register_error_handler(502, gateway_error) init_logs(app) init_events(app) init_plugins(app) return app
app = Flask(__name__) with app.app_context(): args = process_args(args) from CTFd.models import db app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False url = make_url(app.config['SQLALCHEMY_DATABASE_URI']) if url.drivername == 'postgres': url.drivername = 'postgresql' db.init_app(app) from CTFd.cache import cache cache.init_app(app) try: if not (url.drivername.startswith('sqlite') or database_exists(url)): create_database(url) db.create_all() except OperationalError: db.create_all() else: db.create_all() app.db = db import_challenges(args.in_file, args.dst_attachments, args.exit_on_error,