Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4ff203c

Browse files
henry3260dominikhei
authored andcommitted
fab: centralize FastAPI auth manager routing (apache#61647)
* fab: centralize FastAPI auth manager routing * Add register_routes
1 parent 95c453e commit 4ff203c

6 files changed

Lines changed: 96 additions & 31 deletions

File tree

providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/routes/login.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@
2323

2424
from airflow.api_fastapi.app import get_auth_manager
2525
from airflow.api_fastapi.auth.managers.base_auth_manager import COOKIE_NAME_JWT_TOKEN
26-
from airflow.api_fastapi.common.router import AirflowRouter
2726
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
2827
from airflow.configuration import conf
2928
from airflow.providers.fab.auth_manager.api_fastapi.datamodels.login import LoginResponse
29+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import auth_router
3030
from airflow.providers.fab.auth_manager.api_fastapi.services.login import FABAuthManagerLogin
3131
from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
3232

33-
login_router = AirflowRouter(tags=["FabAuthManager"])
3433

35-
36-
@login_router.post(
34+
@auth_router.post(
3735
"/token",
3836
response_model=LoginResponse,
3937
status_code=status.HTTP_201_CREATED,
@@ -45,7 +43,7 @@ def create_token(request: Request, body: dict[str, Any] = Body(...)) -> LoginRes
4543
return FABAuthManagerLogin.create_token(headers=dict(request.headers), body=body)
4644

4745

48-
@login_router.post(
46+
@auth_router.post(
4947
"/token/cli",
5048
response_model=LoginResponse,
5149
status_code=status.HTTP_201_CREATED,
@@ -61,7 +59,7 @@ def create_token_cli(request: Request, body: dict[str, Any] = Body(...)) -> Logi
6159
)
6260

6361

64-
@login_router.get(
62+
@auth_router.get(
6563
"/logout",
6664
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
6765
)

providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/routes/roles.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
from fastapi import Depends, Path, Query, status
2020

21-
from airflow.api_fastapi.common.router import AirflowRouter
2221
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
2322
from airflow.providers.fab.auth_manager.api_fastapi.datamodels.roles import (
2423
PermissionCollectionResponse,
@@ -27,15 +26,14 @@
2726
RoleResponse,
2827
)
2928
from airflow.providers.fab.auth_manager.api_fastapi.parameters import get_effective_limit
29+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import fab_router
3030
from airflow.providers.fab.auth_manager.api_fastapi.security import requires_fab_custom_view
3131
from airflow.providers.fab.auth_manager.api_fastapi.services.roles import FABAuthManagerRoles
3232
from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
3333
from airflow.providers.fab.www.security import permissions
3434

35-
roles_router = AirflowRouter(prefix="/fab/v1", tags=["FabAuthManager"])
3635

37-
38-
@roles_router.post(
36+
@fab_router.post(
3937
"/roles",
4038
responses=create_openapi_http_exception_doc(
4139
[
@@ -54,7 +52,7 @@ def create_role(body: RoleBody) -> RoleResponse:
5452
return FABAuthManagerRoles.create_role(body=body)
5553

5654

57-
@roles_router.get(
55+
@fab_router.get(
5856
"/roles",
5957
response_model=RoleCollectionResponse,
6058
responses=create_openapi_http_exception_doc(
@@ -77,7 +75,7 @@ def get_roles(
7775
return FABAuthManagerRoles.get_roles(order_by=order_by, limit=limit, offset=offset)
7876

7977

80-
@roles_router.delete(
78+
@fab_router.delete(
8179
"/roles/{name}",
8280
responses=create_openapi_http_exception_doc(
8381
[
@@ -94,7 +92,7 @@ def delete_role(name: str = Path(..., min_length=1)) -> None:
9492
return FABAuthManagerRoles.delete_role(name=name)
9593

9694

97-
@roles_router.get(
95+
@fab_router.get(
9896
"/roles/{name}",
9997
responses=create_openapi_http_exception_doc(
10098
[status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN, status.HTTP_404_NOT_FOUND]
@@ -107,7 +105,7 @@ def get_role(name: str = Path(..., min_length=1)) -> RoleResponse:
107105
return FABAuthManagerRoles.get_role(name=name)
108106

109107

110-
@roles_router.patch(
108+
@fab_router.patch(
111109
"/roles/{name}",
112110
responses=create_openapi_http_exception_doc(
113111
[
@@ -129,7 +127,7 @@ def patch_role(
129127
return FABAuthManagerRoles.patch_role(name=name, body=body, update_mask=update_mask)
130128

131129

132-
@roles_router.get(
130+
@fab_router.get(
133131
"/permissions",
134132
response_model=PermissionCollectionResponse,
135133
responses=create_openapi_http_exception_doc(
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
from __future__ import annotations
18+
19+
from enum import Enum
20+
21+
from airflow.api_fastapi.common.router import AirflowRouter
22+
23+
FAB_AUTH_TAGS: list[str | Enum] = ["FabAuthManager"]
24+
FAB_AUTH_PREFIX = "/fab/v1"
25+
26+
auth_router = AirflowRouter(tags=FAB_AUTH_TAGS)
27+
fab_router = AirflowRouter(prefix=FAB_AUTH_PREFIX, tags=FAB_AUTH_TAGS)
28+
29+
30+
def register_routes() -> None:
31+
"""Register FastAPI routes by importing modules for side effects."""
32+
import importlib
33+
34+
importlib.import_module("airflow.providers.fab.auth_manager.api_fastapi.routes.login")
35+
importlib.import_module("airflow.providers.fab.auth_manager.api_fastapi.routes.roles")
36+
importlib.import_module("airflow.providers.fab.auth_manager.api_fastapi.routes.users")

providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/routes/users.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
from fastapi import Depends, Path, Query, status
2020

21-
from airflow.api_fastapi.common.router import AirflowRouter
2221
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
2322
from airflow.providers.fab.auth_manager.api_fastapi.datamodels.users import (
2423
UserBody,
@@ -27,15 +26,14 @@
2726
UserResponse,
2827
)
2928
from airflow.providers.fab.auth_manager.api_fastapi.parameters import get_effective_limit
29+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import fab_router
3030
from airflow.providers.fab.auth_manager.api_fastapi.security import requires_fab_custom_view
3131
from airflow.providers.fab.auth_manager.api_fastapi.services.users import FABAuthManagerUsers
3232
from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
3333
from airflow.providers.fab.www.security import permissions
3434

35-
users_router = AirflowRouter(prefix="/fab/v1", tags=["FabAuthManager"])
3635

37-
38-
@users_router.post(
36+
@fab_router.post(
3937
"/users",
4038
responses=create_openapi_http_exception_doc(
4139
[
@@ -53,7 +51,7 @@ def create_user(body: UserBody) -> UserResponse:
5351
return FABAuthManagerUsers.create_user(body=body)
5452

5553

56-
@users_router.get(
54+
@fab_router.get(
5755
"/users",
5856
response_model=UserCollectionResponse,
5957
responses=create_openapi_http_exception_doc(
@@ -75,7 +73,7 @@ def get_users(
7573
return FABAuthManagerUsers.get_users(order_by=order_by, limit=limit, offset=offset)
7674

7775

78-
@users_router.get(
76+
@fab_router.get(
7977
"/users/{username}",
8078
responses=create_openapi_http_exception_doc(
8179
[
@@ -92,7 +90,7 @@ def get_user(username: str = Path(..., min_length=1)) -> UserResponse:
9290
return FABAuthManagerUsers.get_user(username=username)
9391

9492

95-
@users_router.patch(
93+
@fab_router.patch(
9694
"/users/{username}",
9795
responses=create_openapi_http_exception_doc(
9896
[
@@ -115,7 +113,7 @@ def update_user(
115113
return FABAuthManagerUsers.update_user(username=username, body=body, update_mask=update_mask)
116114

117115

118-
@users_router.delete(
116+
@fab_router.delete(
119117
"/users/{username}",
120118
status_code=status.HTTP_204_NO_CONTENT,
121119
responses=create_openapi_http_exception_doc(

providers/fab/src/airflow/providers/fab/auth_manager/fab_auth_manager.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,11 @@ def get_cli_commands() -> list[CLICommand]:
200200

201201
def get_fastapi_app(self) -> FastAPI | None:
202202
"""Get the FastAPI app."""
203-
from airflow.providers.fab.auth_manager.api_fastapi.routes.login import (
204-
login_router,
203+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import (
204+
auth_router,
205+
fab_router,
206+
register_routes,
205207
)
206-
from airflow.providers.fab.auth_manager.api_fastapi.routes.roles import roles_router
207-
from airflow.providers.fab.auth_manager.api_fastapi.routes.users import users_router
208208

209209
flask_app = create_app(enable_plugins=False)
210210

@@ -218,10 +218,9 @@ def get_fastapi_app(self) -> FastAPI | None:
218218
),
219219
)
220220

221-
# Add the login router to the FastAPI app
222-
app.include_router(login_router)
223-
app.include_router(roles_router)
224-
app.include_router(users_router)
221+
register_routes()
222+
app.include_router(auth_router)
223+
app.include_router(fab_router)
225224

226225
# Session cleanup middleware to prevent PendingRollbackError.
227226
# FAB's Flask views (e.g., /users/list/, /roles/list/) are mounted below via
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
from __future__ import annotations
19+
20+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import (
21+
FAB_AUTH_PREFIX,
22+
auth_router,
23+
fab_router,
24+
)
25+
26+
27+
def test_root_routers_share_tags() -> None:
28+
assert auth_router.tags == fab_router.tags
29+
30+
31+
def test_fab_router_prefix() -> None:
32+
assert fab_router.prefix == FAB_AUTH_PREFIX
33+
34+
35+
def test_auth_router_prefix() -> None:
36+
assert auth_router.prefix == ""

0 commit comments

Comments
 (0)