diff --git a/flaschengeist/app.py b/flaschengeist/app.py index ad44085..1a80aa0 100644 --- a/flaschengeist/app.py +++ b/flaschengeist/app.py @@ -71,7 +71,7 @@ def install_all(): roleController.create_permissions(plugin.permissions) -def create_app(): +def create_app(test_config=None): app = Flask(__name__) app.json_encoder = CustomJSONEncoder CORS(app) @@ -79,7 +79,7 @@ def create_app(): with app.app_context(): from flaschengeist.database import db - configure_app(app) + configure_app(app, test_config) db.init_app(app) __load_plugins(app) diff --git a/flaschengeist/config.py b/flaschengeist/config.py index 1ae840f..e8726c6 100644 --- a/flaschengeist/config.py +++ b/flaschengeist/config.py @@ -8,33 +8,44 @@ from werkzeug.middleware.proxy_fix import ProxyFix from flaschengeist import _module_path, logger -def __update(d, u): +# Default config: +config = {} + + +def update_dict(d, u): for k, v in u.items(): if isinstance(v, collections.abc.Mapping): - d[k] = __update(d.get(k, {}), v) + d[k] = update_dict(d.get(k, {}), v) else: d[k] = v return d -# Default config: -config = {} +def read_configuration(): + global config -__paths = [_module_path, Path.home() / ".config"] -if "FLASCHENGEIST_CONF" in os.environ: - __paths.append(Path(os.environ.get("FLASCHENGEIST_CONF"))) -for loc in __paths: - try: - with (loc / "flaschengeist.toml").open() as source: - logger.info("Reading config file from >{}<".format(loc)) - __update(config, toml.load(source)) - except IOError: - pass -# Always enable this builtin plugins! -__update(config, {"auth": {"enabled": True}, "roles": {"enabled": True}, "users": {"enabled": True}}) + paths = [_module_path, Path.home() / ".config"] + if "FLASCHENGEIST_CONF" in os.environ: + paths.append(Path(os.environ.get("FLASCHENGEIST_CONF"))) + + for loc in paths: + try: + with (loc / "flaschengeist.toml").open() as source: + print("Reading config file from >{}<".format(loc)) + update_dict(config, toml.load(source)) + except IOError: + pass -def configure_app(app): +def configure_app(app, test_config=None): + global config + if test_config is None: + read_configuration() + else: + update_dict(config, test_config) + # Always enable this builtin plugins! + update_dict(config, {"auth": {"enabled": True}, "roles": {"enabled": True}, "users": {"enabled": True}}) + logger_config = toml.load(_module_path / "logging.toml") if "LOGGING" in config: if "level" in config["LOGGING"]: @@ -52,12 +63,15 @@ def configure_app(app): else: app.config["SECRET_KEY"] = config["FLASCHENGEIST"]["secret_key"] - app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://{user}:{passwd}@{host}/{database}".format( - user=config["DATABASE"]["user"], - passwd=config["DATABASE"]["password"], - host=config["DATABASE"]["host"], - database=config["DATABASE"]["database"], - ) + if test_config is None: + app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://{user}:{passwd}@{host}/{database}".format( + user=config["DATABASE"]["user"], + passwd=config["DATABASE"]["password"], + host=config["DATABASE"]["host"], + database=config["DATABASE"]["database"], + ) + else: + app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite+pysqlite://{config['DATABASE']['file_path']}" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False if "root" in config["FLASCHENGEIST"]: diff --git a/setup.py b/setup.py index d97177b..97d3100 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ setup( # Needed for python < 3.7 "backports-datetime-fromisoformat", ], - extras_require={"ldap": ["flask_ldapconn", "ldap3"]}, + extras_require={"ldap": ["flask_ldapconn", "ldap3"], "tests": ["pytest"]}, entry_points={ "flaschengeist.plugin": [ # Authentication providers diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0c0931b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,28 @@ +import os +import tempfile +import pytest + +from flaschengeist.app import create_app, install_all + + +@pytest.fixture +def app(): + db_fd, db_path = tempfile.mkstemp() + app = create_app( + { + "TESTING": True, + "DATABASE": {"file_path": f"/{db_path}"}, + "FLASCHENGEIST": {"auth": "auth_plain"}, + "auth_plain": {"enabled": True}, + } + ) + with app.app_context(): + install_all() + yield app + os.close(db_fd) + os.unlink(db_path) + + +@pytest.fixture +def client(app): + return app.test_client() diff --git a/tests/test_auth.py b/tests/test_auth.py new file mode 100644 index 0000000..6dcf468 --- /dev/null +++ b/tests/test_auth.py @@ -0,0 +1,16 @@ +import pytest + +# with app.app_context(): +# engine = database.db.engine +# with engine.connect() as connection: +# connection.execute("") + + +def test_login_decorator(client): + """Testing the login_required decorator""" + # No header at all + assert client.get("/auth").status_code == 401 + # Invalid header + assert client.get("/auth", headers={"Authorization": "INVALID"}).status_code == 401 + # Invalid Token + assert client.get("/auth", headers={"Authorization": "Bearer INVALID"}).status_code == 401