diff --git a/application/api/admin/routes.py b/application/api/admin/routes.py index b921dd4e..5676679f 100644 --- a/application/api/admin/routes.py +++ b/application/api/admin/routes.py @@ -18,7 +18,6 @@ from datetime import datetime, timedelta, timezone from flask import jsonify, make_response, request from flask_restx import Namespace, Resource -from application.api import api from application.api.oidc import denylist from application.api.user.authz import ROLE_ADMIN, admin_required from application.storage.db.repositories.admin_stats import AdminStatsRepository @@ -374,10 +373,3 @@ class AdminDeviceAuditResource(Resource): ), 200, ) - - -# Register here, in this import-cached module, rather than in app.py's body so a -# re-import of application.app (coverage tests reload the module) doesn't re-fire -# add_namespace against the already-initialized Api. app.py imports this module -# for the side effect. -api.add_namespace(admin_ns) diff --git a/application/app.py b/application/app.py index aec9f13f..ad9f0140 100644 --- a/application/app.py +++ b/application/app.py @@ -15,7 +15,7 @@ from application.core.logging_config import setup_logging setup_logging() from application.api import api # noqa: E402 -from application.api.admin import routes as _admin_routes # noqa: E402,F401 (registers admin_ns) +from application.api.admin import admin_ns # noqa: E402 from application.api.answer import answer # noqa: E402 from application.api.devices import devices_bp # noqa: E402 from application.api.events.routes import events # noqa: E402 @@ -69,6 +69,12 @@ app.register_blueprint(devices_bp) app.register_blueprint(oidc_bp) app.register_blueprint(scim_bp) app.register_blueprint(v1_bp) +# Register the admin namespace once. The membership guard makes this idempotent +# if application.app is re-imported (coverage tests reload the module): without +# it, re-running add_namespace would re-register routes on the already-served +# first app and raise "add_url_rule can no longer be called". +if admin_ns not in api.namespaces: + api.add_namespace(admin_ns) app.config.update( UPLOAD_FOLDER="inputs", CELERY_BROKER_URL=settings.CELERY_BROKER_URL,