Skip to content

Commit c05abfb

Browse files
committed
fab: centralize FastAPI auth manager routing
1 parent bfaf4ff commit c05abfb

File tree

6 files changed

+90
-32
lines changed

6 files changed

+90
-32
lines changed

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 & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
from fastapi import Depends, Path, Query, status
2222

23-
from airflow.api_fastapi.common.router import AirflowRouter
2423
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
2524
from airflow.providers.fab.auth_manager.api_fastapi.datamodels.roles import (
2625
PermissionCollectionResponse,
@@ -29,6 +28,7 @@
2928
RoleResponse,
3029
)
3130
from airflow.providers.fab.auth_manager.api_fastapi.parameters import get_effective_limit
31+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import fab_router
3232
from airflow.providers.fab.auth_manager.api_fastapi.security import requires_fab_custom_view
3333
from airflow.providers.fab.auth_manager.api_fastapi.services.roles import FABAuthManagerRoles
3434
from airflow.providers.fab.auth_manager.cli_commands.utils import get_application_builder
@@ -41,10 +41,7 @@
4141
)
4242

4343

44-
roles_router = AirflowRouter(prefix="/fab/v1", tags=["FabAuthManager"])
45-
46-
47-
@roles_router.post(
44+
@fab_router.post(
4845
"/roles",
4946
responses=create_openapi_http_exception_doc(
5047
[
@@ -63,7 +60,7 @@ def create_role(body: RoleBody) -> RoleResponse:
6360
return FABAuthManagerRoles.create_role(body=body)
6461

6562

66-
@roles_router.get(
63+
@fab_router.get(
6764
"/roles",
6865
response_model=RoleCollectionResponse,
6966
responses=create_openapi_http_exception_doc(
@@ -86,7 +83,7 @@ def get_roles(
8683
return FABAuthManagerRoles.get_roles(order_by=order_by, limit=limit, offset=offset)
8784

8885

89-
@roles_router.delete(
86+
@fab_router.delete(
9087
"/roles/{name}",
9188
responses=create_openapi_http_exception_doc(
9289
[
@@ -103,7 +100,7 @@ def delete_role(name: str = Path(..., min_length=1)) -> None:
103100
return FABAuthManagerRoles.delete_role(name=name)
104101

105102

106-
@roles_router.get(
103+
@fab_router.get(
107104
"/roles/{name}",
108105
responses=create_openapi_http_exception_doc(
109106
[status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN, status.HTTP_404_NOT_FOUND]
@@ -116,7 +113,7 @@ def get_role(name: str = Path(..., min_length=1)) -> RoleResponse:
116113
return FABAuthManagerRoles.get_role(name=name)
117114

118115

119-
@roles_router.patch(
116+
@fab_router.patch(
120117
"/roles/{name}",
121118
responses=create_openapi_http_exception_doc(
122119
[
@@ -138,7 +135,7 @@ def patch_role(
138135
return FABAuthManagerRoles.patch_role(name=name, body=body, update_mask=update_mask)
139136

140137

141-
@roles_router.get(
138+
@fab_router.get(
142139
"/permissions",
143140
response_model=PermissionCollectionResponse,
144141
responses=create_openapi_http_exception_doc(
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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)

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: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,15 @@ def get_cli_commands() -> list[CLICommand]:
198198

199199
def get_fastapi_app(self) -> FastAPI | None:
200200
"""Get the FastAPI app."""
201-
from airflow.providers.fab.auth_manager.api_fastapi.routes.login import (
202-
login_router,
201+
from airflow.providers.fab.auth_manager.api_fastapi.routes import (
202+
login as _login, # noqa: F401
203+
roles as _roles, # noqa: F401
204+
users as _users, # noqa: F401
205+
)
206+
from airflow.providers.fab.auth_manager.api_fastapi.routes.router import (
207+
auth_router,
208+
fab_router,
203209
)
204-
from airflow.providers.fab.auth_manager.api_fastapi.routes.roles import roles_router
205-
from airflow.providers.fab.auth_manager.api_fastapi.routes.users import users_router
206210

207211
flask_app = create_app(enable_plugins=False)
208212

@@ -216,10 +220,8 @@ def get_fastapi_app(self) -> FastAPI | None:
216220
),
217221
)
218222

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

224226
app.mount("/", WSGIMiddleware(flask_app))
225227

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)