From a87a9735d52f7bd9dad32dc7898db6fc741ec418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Wed, 11 Oct 2023 15:33:33 +0200 Subject: [PATCH 1/2] refactor: split application initialization in several methods --- web/flaskr/__init__.py | 67 +++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/web/flaskr/__init__.py b/web/flaskr/__init__.py index 6ff8749f..14eb48b7 100755 --- a/web/flaskr/__init__.py +++ b/web/flaskr/__init__.py @@ -25,19 +25,7 @@ LANGUAGES = ["en", "fr"] -def setup_babel(app): - babel = Babel(app) - - @babel.localeselector - def get_locale(): - if request.args.get("lang"): - session["lang"] = request.args["lang"] - return session.get("lang", "fr") - - -def create_app(test_config=None, gunicorn_logging=False): - # create and configure the app - app = Flask(__name__, instance_relative_config=True) +def setup_cache(app): cache.init_app( app, config={ @@ -45,6 +33,9 @@ def create_app(test_config=None, gunicorn_logging=False): "CACHE_DIR": "/tmp/flask-caching", }, ) + + +def setup_logging(app, test_config=None, gunicorn_logging=False): if gunicorn_logging: gunicorn_logger = logging.getLogger("gunicorn.error") app.logger.handlers = gunicorn_logger.handlers @@ -53,25 +44,23 @@ def create_app(test_config=None, gunicorn_logging=False): if test_config: app.config.from_mapping(test_config) - @app.context_processor - def global_processor(): - return { - "config": app.config, - "beta": app.config["BETA"], - "documentation_link": app.config["DOCUMENTATION_LINK"], - "is_rie": is_rie(), - "LANGUAGES": LANGUAGES, - **app.config["WORDINGS"], - } - # translations - setup_babel(app) +def setup_i18n(app): + babel = Babel(app) + + @babel.localeselector + def get_locale(): + if request.args.get("lang"): + session["lang"] = request.args["lang"] + return session.get("lang", "fr") + - # Protect App Form with CSRF +def setup_csrf(app): csrf = CSRFProtect() csrf.init_app(app) - # init database + +def setup_database(app): with app.app_context(): import flaskr.routes @@ -81,6 +70,30 @@ def global_processor(): db.init_app(app) Migrate(app, db, compare_type=True) + +def setup_jinja(app): + @app.context_processor + def global_processor(): + return { + "config": app.config, + "beta": app.config["BETA"], + "documentation_link": app.config["DOCUMENTATION_LINK"], + "is_rie": is_rie(), + "LANGUAGES": LANGUAGES, + **app.config["WORDINGS"], + } + + +def create_app(test_config=None, gunicorn_logging=False): + # create and configure the app + app = Flask(__name__, instance_relative_config=True) + setup_cache(app) + setup_logging(app, test_config, gunicorn_logging) + setup_i18n(app) + setup_csrf(app) + setup_database(app) + setup_jinja(app) + # ensure the instance folder exists os.makedirs(app.instance_path, exist_ok=True) From dd5a1c9438acfcd75ed3d357e25589175fa8579f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Wed, 11 Oct 2023 17:45:26 +0200 Subject: [PATCH 2/2] feat: custom 400 error message --- web/flaskr/__init__.py | 21 +++++++++++++++++ web/flaskr/routes.py | 30 ------------------------ web/flaskr/templates/errors/400.html | 18 +++++++++++++++ web/tests/test_default.py | 34 ++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 web/flaskr/templates/errors/400.html diff --git a/web/flaskr/__init__.py b/web/flaskr/__init__.py index 14eb48b7..6ef16f1a 100755 --- a/web/flaskr/__init__.py +++ b/web/flaskr/__init__.py @@ -84,6 +84,26 @@ def global_processor(): } +def setup_error_pages(app): + from flask import render_template + + @app.errorhandler(400) + def bad_request(error): + return render_template("errors/400.html", error=error), 400 + + @app.errorhandler(403) + def not_authorized(error): + return render_template("errors/403.html", error=error), 403 + + @app.errorhandler(404) + def not_found(error): + return render_template("errors/404.html", error=error), 404 + + @app.errorhandler(500) + def internal_error(error): + return render_template("errors/500.html", error=error), 500 + + def create_app(test_config=None, gunicorn_logging=False): # create and configure the app app = Flask(__name__, instance_relative_config=True) @@ -93,6 +113,7 @@ def create_app(test_config=None, gunicorn_logging=False): setup_csrf(app) setup_database(app) setup_jinja(app) + setup_error_pages(app) # ensure the instance folder exists os.makedirs(app.instance_path, exist_ok=True) diff --git a/web/flaskr/routes.py b/web/flaskr/routes.py index 50357b09..560e68ea 100755 --- a/web/flaskr/routes.py +++ b/web/flaskr/routes.py @@ -1544,33 +1544,3 @@ def delete_video_meeting(): @auth.oidc_logout def logout(): return redirect(url_for("routes.index")) - - -@current_app.errorhandler(403) -def page_not_authorized(e): - return ( - render_template( - "errors/403.html", - ), - 403, - ) - - -@current_app.errorhandler(404) -def page_not_found(e): - return ( - render_template( - "errors/404.html", - ), - 404, - ) - - -@current_app.errorhandler(500) -def page_error(e): - return ( - render_template( - "errors/500.html", - ), - 500, - ) diff --git a/web/flaskr/templates/errors/400.html b/web/flaskr/templates/errors/400.html new file mode 100644 index 00000000..d42677d6 --- /dev/null +++ b/web/flaskr/templates/errors/400.html @@ -0,0 +1,18 @@ +{% extends 'layout.html' %} + +{% block main %} +
+
+
+

{% trans %}Erreur 400{% endtrans %}

+

+ {% if error %} + {{ error }} + {% else %} + {% trans %}La requête que vous avez effectué est invalide. Vous pouvez retourner à l’accueil.{% endtrans %} + {% endif %} +

+
+
+
+{% endblock %} diff --git a/web/tests/test_default.py b/web/tests/test_default.py index b42d506a..04c42ce0 100644 --- a/web/tests/test_default.py +++ b/web/tests/test_default.py @@ -1,6 +1,40 @@ +from flask import abort from flask import url_for +def test_custom_400(client_app): + @client_app.app.route("/custom_400") + def custom_400(): + abort(400, "custom error message") + + response = client_app.get("/custom_400", status=400) + response.mustcontain("Erreur 400") + response.mustcontain("custom error message") + + +def test_custom_404(client_app): + response = client_app.get("/invalid-url", status=404) + response.mustcontain("Erreur 404") + + +def test_custom_403(client_app): + @client_app.app.route("/custom_403") + def custom_403(): + abort(403) + + response = client_app.get("/custom_403", status=403) + response.mustcontain("Erreur 403") + + +def test_custom_500(client_app): + @client_app.app.route("/custom_500") + def custom_500(): + abort(500) + + response = client_app.get("/custom_500", status=500) + response.mustcontain("Erreur 500") + + def test_root__anonymous_user(client_app): response = client_app.get("/", status=302)