diff --git a/tests/test_site/auth.py b/tests/test_site/auth.py index bb3ff21..577e1ec 100644 --- a/tests/test_site/auth.py +++ b/tests/test_site/auth.py @@ -17,8 +17,10 @@ """The authentication for the Mia! Accounting demonstration website. """ +import typing as t + from flask import Blueprint, render_template, Flask, redirect, url_for, \ - session, request, g, Response + session, request, g, Response, abort from . import db @@ -93,6 +95,31 @@ def current_user() -> User | None: return g.user +def admin_required(view: t.Callable) -> t.Callable: + """The view decorator to require the user to be an administrator. + + :param view: The view. + :return: The decorated view. + """ + + def decorated_view(*args, **kwargs): + """The decorated view that tests against a permission rule. + + :param args: The arguments of the view. + :param kwargs: The keyword arguments of the view. + :return: The response of the view. + :raise Forbidden: When the user is denied. + """ + from accounting.utils.next_uri import append_next + if "user" not in session: + return redirect(append_next(url_for("auth.login"))) + if session["user"] != "admin": + abort(403) + return view(*args, **kwargs) + + return decorated_view + + def init_app(app: Flask) -> None: """Initialize the localization. diff --git a/tests/test_site/reset.py b/tests/test_site/reset.py index 0dc6cf0..b3eb1b3 100644 --- a/tests/test_site/reset.py +++ b/tests/test_site/reset.py @@ -23,8 +23,8 @@ from flask import Flask, Blueprint, url_for, flash, redirect, session, \ render_template, current_app from flask_babel import lazy_gettext -from accounting.utils.cast import s from . import db +from .auth import admin_required from .lib import Accounts, JournalEntryLineItemData, JournalEntryData, \ JournalEntryCurrencyData, BaseTestData @@ -32,6 +32,7 @@ bp: Blueprint = Blueprint("reset", __name__, url_prefix="/") @bp.get("reset", endpoint="reset-page") +@admin_required def reset() -> str: """Resets the sample data. @@ -41,11 +42,13 @@ def reset() -> str: @bp.post("sample", endpoint="sample") +@admin_required def reset_sample() -> redirect: """Resets the sample data. :return: Redirection to the accounting application. """ + from accounting.utils.cast import s __reset_database() SampleData(current_app, "editor").populate() flash(s(lazy_gettext( @@ -54,11 +57,13 @@ def reset_sample() -> redirect: @bp.post("reset", endpoint="clean-up") +@admin_required def clean_up() -> redirect: """Clean-up the database data. :return: Redirection to the accounting application. """ + from accounting.utils.cast import s __reset_database() flash(s(lazy_gettext("The database is emptied successfully.")), "success") return redirect(url_for("accounting-report.default"))