From 33fe8c37b7a96d4f0324c732dcd18f9e5f53d1cb Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Thu, 23 Apr 2026 17:24:04 +0900 Subject: [PATCH 1/6] Prevent FAB auth manager recreation from breaking /auth/token Prevent FAB auth manager recreation from breaking /auth/token When FAB auth manager is initialized for the FastAPI app, the auth manager instance stores the Flask app used by the FAB-backed auth routes. Later, init_appbuilder() recreates the global auth manager instance. That replacement loses the initialized flask_app reference, so /auth/token fails with: "Flask app is not initialized. Check that FabAuthManager started up correctly." Reuse the already initialized auth manager when present and only fall back to create_auth_manager() if initialization has not happened yet. --- .../airflow/providers/fab/www/extensions/init_appbuilder.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index 4662e50a439b4..02b5fe19ee37f 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -196,7 +196,11 @@ def init_app(self, app, session): self._addon_managers = app.config["ADDON_MANAGERS"] self.session = session - auth_manager = create_auth_manager() + try: + auth_manager = get_auth_manager() + except RuntimeError: + auth_manager = create_auth_manager() + with _init_app_lock: auth_manager.appbuilder = self # Invalidate cached security_manager so it binds to the current Flask app. From b3a7b4041ecc03690a63c7fdfb861d4b81c494d6 Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Fri, 24 Apr 2026 10:51:34 +0900 Subject: [PATCH 2/6] Only reuse initialized FAB auth managers in init_appbuilder Only reuse initialized FAB auth managers in init_appbuilder The previous change reused the global auth manager whenever one was already initialized. That was too broad for test environments, where the global auth manager may exist but not be a FabAuthManager. This updates the logic to reuse the existing auth manager only when it is already FAB-backed, and to fall back to reate_auth_manager() otherwise. This preserves the /auth/token fix while avoiding FAB CLI and auth manager test failures caused by reusing a non-FAB auth manager. --- .../airflow/providers/fab/www/extensions/init_appbuilder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index 02b5fe19ee37f..02cb0080baadd 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -165,6 +165,8 @@ def init_app(self, app, session): :param app: :param session: The SQLAlchemy session """ + from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager + log.info("Initializing AppBuilder") app.config.setdefault("APP_NAME", "F.A.B.") app.config.setdefault("APP_THEME", "") @@ -193,14 +195,14 @@ def init_app(self, app, session): self.menu = dynamic_class_import(_menu) else: self.menu = self.menu or Menu() - self._addon_managers = app.config["ADDON_MANAGERS"] self.session = session try: auth_manager = get_auth_manager() except RuntimeError: auth_manager = create_auth_manager() - + if not isinstance(auth_manager, FabAuthManager): + auth_manager = create_auth_manager() with _init_app_lock: auth_manager.appbuilder = self # Invalidate cached security_manager so it binds to the current Flask app. From 288ce82a5954aa56ff13d3afb42b96b2b3133144 Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Fri, 24 Apr 2026 14:32:46 +0900 Subject: [PATCH 3/6] Keep FAB auth manager import formatting hook-compliant Remove trailing whitespace from the blank line after the local FabAuthManager import in AppBuilder initialization. The import remains visually separated from the executable setup code, while matching the format expected by pre-commit hooks so CI does not fail with hook-made changes. --- .../src/airflow/providers/fab/www/extensions/init_appbuilder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index 02cb0080baadd..3f55e4213011e 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -166,7 +166,7 @@ def init_app(self, app, session): :param session: The SQLAlchemy session """ from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager - + log.info("Initializing AppBuilder") app.config.setdefault("APP_NAME", "F.A.B.") app.config.setdefault("APP_THEME", "") From 2095d55c4e006a4574552962b5c4387fa7f8cd5a Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Sat, 25 Apr 2026 01:34:18 +0900 Subject: [PATCH 4/6] Use get_fab_auth_manager() to avoid duplicate FAB type checks Replace the generic auth-manager lookup in init_appbuilder with get_fab_auth_manager(), which already guarantees a FabAuthManager instance or raises when the configured manager is not FAB-based. --- .../airflow/providers/fab/www/extensions/init_appbuilder.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index 3f55e4213011e..f14de4d07e7d0 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -198,11 +198,9 @@ def init_app(self, app, session): self._addon_managers = app.config["ADDON_MANAGERS"] self.session = session try: - auth_manager = get_auth_manager() + auth_manager = get_fab_auth_manager() except RuntimeError: auth_manager = create_auth_manager() - if not isinstance(auth_manager, FabAuthManager): - auth_manager = create_auth_manager() with _init_app_lock: auth_manager.appbuilder = self # Invalidate cached security_manager so it binds to the current Flask app. From e26bf23b7bed8fc7c34b2525053ac6747c7e888d Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Sat, 25 Apr 2026 02:56:17 +0900 Subject: [PATCH 5/6] Update init_appbuilder.py add import get_fab_auth_manager --- .../src/airflow/providers/fab/www/extensions/init_appbuilder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index f14de4d07e7d0..15dfb9c109e8d 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -165,7 +165,7 @@ def init_app(self, app, session): :param app: :param session: The SQLAlchemy session """ - from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager + from airflow.providers.fab.auth_manager.fab_auth_manager import get_fab_auth_manager log.info("Initializing AppBuilder") app.config.setdefault("APP_NAME", "F.A.B.") From ffacc77803fdb2a4ed40d67e2b6880eb2f0d8d52 Mon Sep 17 00:00:00 2001 From: Ethan_1000 Date: Sat, 25 Apr 2026 02:58:07 +0900 Subject: [PATCH 6/6] Update init_appbuilder.py --- .../src/airflow/providers/fab/www/extensions/init_appbuilder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py index 15dfb9c109e8d..7a6d8c6d8949d 100644 --- a/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py +++ b/providers/fab/src/airflow/providers/fab/www/extensions/init_appbuilder.py @@ -165,7 +165,7 @@ def init_app(self, app, session): :param app: :param session: The SQLAlchemy session """ - from airflow.providers.fab.auth_manager.fab_auth_manager import get_fab_auth_manager + from airflow.providers.fab.www.utils import get_fab_auth_manager log.info("Initializing AppBuilder") app.config.setdefault("APP_NAME", "F.A.B.")