diff --git a/CTFd/config.ini b/CTFd/config.ini index 39862542..1c22bd3d 100644 --- a/CTFd/config.ini +++ b/CTFd/config.ini @@ -26,10 +26,38 @@ SECRET_KEY = # The URI that specifies the username, password, hostname, port, and database of the server # used to hold the CTFd database. # -# If a database URL is not specified, CTFd will automatically create a SQLite database for you to use +# If neither this setting nor `DATABASE_HOST` is specified, CTFd will automatically create a SQLite database for you to use # e.g. mysql+pymysql://root:@localhost/ctfd DATABASE_URL = +# DATABASE_HOST +# The hostname of the database server used to hold the CTFd database. +# If `DATABASE_URL` is set, this setting will have no effect. +# +# This option, along with the other `DATABASE_*` options, are an alternative to specifying all connection details in the single `DATABASE_URL`. +# If neither this setting nor `DATABASE_URL` is specified, CTFd will automatically create a SQLite database for you to use. +DATABASE_HOST = + +# DATABASE_PROTOCOL +# The protocol used to access the database server, if `DATABASE_HOST` is set. Defaults to `mysql+pymysql`. +DATABASE_PROTOCOL = + +# DATABASE_USER +# The username used to access the database server, if `DATABASE_HOST` is set. Defaults to `ctfd`. +DATABASE_USER = + +# DATABASE_PASSWORD +# The password used to access the database server, if `DATABASE_HOST` is set. +DATABASE_PASSWORD = + +# DATABASE_PORT +# The port used to access the database server, if `DATABASE_HOST` is set. +DATABASE_PORT = + +# DATABASE_NAME +# The name of the database to access on the database server, if `DATABASE_HOST` is set. Defaults to `ctfd`. +DATABASE_NAME = + # REDIS_URL # The URL to connect to a Redis server. If not specified, CTFd will use the .data folder as a filesystem cache # diff --git a/CTFd/config.py b/CTFd/config.py index 9a31ac13..584ec71a 100644 --- a/CTFd/config.py +++ b/CTFd/config.py @@ -3,6 +3,8 @@ import os from distutils.util import strtobool from typing import Union +from sqlalchemy.engine.url import URL + class EnvInterpolation(configparser.BasicInterpolation): """Interpolation which expands environment variables in values.""" @@ -83,8 +85,21 @@ class ServerConfig(object): SECRET_KEY: str = empty_str_cast(config_ini["server"]["SECRET_KEY"]) \ or gen_secret_key() - DATABASE_URL: str = empty_str_cast(config_ini["server"]["DATABASE_URL"]) \ - or f"sqlite:///{os.path.dirname(os.path.abspath(__file__))}/ctfd.db" + DATABASE_URL: str = empty_str_cast(config_ini["server"]["DATABASE_URL"]) + if not DATABASE_URL: + if empty_str_cast(config_ini["server"]["DATABASE_HOST"]) is not None: + # construct URL from individual variables + DATABASE_URL = str(URL( + drivername=empty_str_cast(config_ini["server"]["DATABASE_PROTOCOL"]) or "mysql+pymysql", + username=empty_str_cast(config_ini["server"]["DATABASE_USER"]) or "ctfd", + password=empty_str_cast(config_ini["server"]["DATABASE_PASSWORD"]), + host=empty_str_cast(config_ini["server"]["DATABASE_HOST"]), + port=empty_str_cast(config_ini["server"]["DATABASE_PORT"]), + database=empty_str_cast(config_ini["server"]["DATABASE_NAME"]) or "ctfd", + )) + else: + # default to local SQLite DB + DATABASE_URL = f"sqlite:///{os.path.dirname(os.path.abspath(__file__))}/ctfd.db" REDIS_URL: str = empty_str_cast(config_ini["server"]["REDIS_URL"])