apache-airflow-providers-fab 2.0.0rc1__py3-none-any.whl → 2.0.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. airflow/providers/fab/LICENSE +0 -52
  2. airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.py +3 -4
  3. airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.py +4 -4
  4. airflow/providers/fab/auth_manager/api/auth/backend/session.py +1 -1
  5. airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.py +14 -14
  6. airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.py +12 -13
  7. airflow/providers/fab/auth_manager/api_fastapi/__init__.py +16 -0
  8. airflow/providers/fab/auth_manager/api_fastapi/datamodels/__init__.py +16 -0
  9. airflow/providers/fab/auth_manager/api_fastapi/datamodels/login.py +32 -0
  10. airflow/providers/fab/auth_manager/api_fastapi/openapi/__init__.py +16 -0
  11. airflow/providers/fab/auth_manager/api_fastapi/openapi/v1-generated.yaml +153 -0
  12. airflow/providers/fab/auth_manager/api_fastapi/routes/__init__.py +16 -0
  13. airflow/providers/fab/auth_manager/api_fastapi/routes/login.py +51 -0
  14. airflow/providers/fab/auth_manager/api_fastapi/services/__init__.py +16 -0
  15. airflow/providers/fab/auth_manager/api_fastapi/services/login.py +58 -0
  16. airflow/providers/fab/auth_manager/cli_commands/db_command.py +2 -4
  17. airflow/providers/fab/auth_manager/cli_commands/user_command.py +2 -2
  18. airflow/providers/fab/auth_manager/cli_commands/utils.py +17 -4
  19. airflow/providers/fab/auth_manager/fab_auth_manager.py +222 -119
  20. airflow/providers/fab/auth_manager/models/__init__.py +1 -1
  21. airflow/providers/fab/auth_manager/models/anonymous_user.py +1 -1
  22. airflow/providers/fab/auth_manager/models/db.py +22 -5
  23. airflow/providers/fab/auth_manager/openapi/v1.yaml +9 -0
  24. airflow/providers/fab/auth_manager/schemas/user_schema.py +1 -1
  25. airflow/providers/fab/auth_manager/security_manager/override.py +89 -561
  26. airflow/providers/fab/auth_manager/views/permissions.py +1 -1
  27. airflow/providers/fab/auth_manager/views/roles_list.py +1 -1
  28. airflow/providers/fab/auth_manager/views/user.py +1 -1
  29. airflow/providers/fab/auth_manager/views/user_edit.py +1 -1
  30. airflow/providers/fab/auth_manager/views/user_stats.py +1 -1
  31. airflow/providers/fab/get_provider_info.py +26 -15
  32. airflow/providers/fab/www/airflow_flask_app.py +31 -0
  33. airflow/providers/fab/www/api_connexion/exceptions.py +197 -0
  34. airflow/providers/fab/www/api_connexion/parameters.py +131 -0
  35. airflow/providers/fab/www/api_connexion/security.py +84 -0
  36. airflow/providers/fab/www/api_connexion/types.py +30 -0
  37. airflow/providers/fab/www/app.py +34 -9
  38. airflow/providers/fab/www/auth.py +350 -0
  39. airflow/providers/fab/www/constants.py +28 -0
  40. airflow/providers/fab/www/extensions/init_appbuilder.py +54 -9
  41. airflow/providers/fab/www/extensions/init_jinja_globals.py +5 -3
  42. airflow/providers/fab/www/extensions/init_security.py +19 -0
  43. airflow/providers/fab/www/extensions/init_session.py +64 -0
  44. airflow/providers/fab/www/extensions/init_views.py +111 -1
  45. airflow/providers/fab/www/package-lock.json +4967 -16517
  46. airflow/providers/fab/www/package.json +25 -104
  47. airflow/providers/fab/www/security/__init__.py +17 -0
  48. airflow/providers/fab/www/security/permissions.py +126 -0
  49. airflow/providers/fab/www/security_appless.py +44 -0
  50. airflow/providers/fab/www/security_manager.py +122 -0
  51. airflow/providers/fab/www/session.py +41 -0
  52. airflow/providers/fab/www/static/css/flash.css +57 -0
  53. airflow/providers/fab/www/static/dist/48f0ea180c40270a5b05.png +1 -0
  54. airflow/providers/fab/www/static/dist/649c0b07771e68fafdeb.png +1 -0
  55. airflow/providers/fab/www/static/dist/airflowDefaultTheme.feec4a4075c2f3d6ae01.css +33 -0
  56. airflow/providers/fab/www/static/dist/airflowDefaultTheme.feec4a4075c2f3d6ae01.js +1 -0
  57. airflow/providers/fab/www/static/dist/f7490d556a6c42e49ba4.png +1 -0
  58. airflow/providers/fab/www/static/dist/flash.137b30cff85b5588e661.css +18 -0
  59. airflow/providers/fab/www/static/dist/flash.137b30cff85b5588e661.js +1 -0
  60. airflow/providers/fab/www/static/dist/jquery-ui.min.css +5 -0
  61. airflow/providers/fab/www/static/dist/jquery-ui.min.js +2 -0
  62. airflow/providers/fab/www/static/dist/jquery-ui.min.js.LICENSE.txt +4 -0
  63. airflow/providers/fab/www/static/dist/loadingDots.48ab7d5b04e66f2686b0.css +18 -0
  64. airflow/providers/fab/www/static/dist/loadingDots.48ab7d5b04e66f2686b0.js +1 -0
  65. airflow/providers/fab/www/static/dist/main.edb2d40dfbbc537916e3.css +18 -0
  66. airflow/providers/fab/www/static/dist/main.edb2d40dfbbc537916e3.js +2 -0
  67. airflow/providers/fab/www/static/dist/main.edb2d40dfbbc537916e3.js.LICENSE.txt +18 -0
  68. airflow/providers/fab/www/static/dist/manifest.json +20 -0
  69. airflow/providers/fab/www/static/dist/materialIcons.57390fa60d8f61175334.css +18 -0
  70. airflow/providers/fab/www/static/dist/materialIcons.57390fa60d8f61175334.js +1 -0
  71. airflow/providers/fab/www/static/dist/moment.624b1f00ba723d39ce06.js +2 -0
  72. airflow/providers/fab/www/static/dist/moment.624b1f00ba723d39ce06.js.LICENSE.txt +11 -0
  73. airflow/providers/fab/www/static/dist/oss-licenses.json +20 -0
  74. airflow/providers/fab/www/templates/airflow/main.html +10 -11
  75. airflow/providers/fab/www/templates/airflow/traceback.html +1 -5
  76. airflow/providers/fab/www/templates/appbuilder/flash.html +34 -0
  77. airflow/providers/fab/www/templates/appbuilder/navbar.html +7 -0
  78. airflow/providers/fab/www/templates/appbuilder/navbar_right.html +64 -0
  79. airflow/providers/fab/www/utils.py +272 -0
  80. airflow/providers/fab/www/views.py +129 -0
  81. airflow/providers/fab/www/webpack.config.js +5 -40
  82. {apache_airflow_providers_fab-2.0.0rc1.dist-info → apache_airflow_providers_fab-2.0.0rc2.dist-info}/METADATA +24 -34
  83. apache_airflow_providers_fab-2.0.0rc2.dist-info/RECORD +125 -0
  84. {apache_airflow_providers_fab-2.0.0rc1.dist-info → apache_airflow_providers_fab-2.0.0rc2.dist-info}/WHEEL +1 -1
  85. airflow/providers/fab/auth_manager/decorators/auth.py +0 -127
  86. apache_airflow_providers_fab-2.0.0rc1.dist-info/RECORD +0 -78
  87. /airflow/providers/fab/{auth_manager/decorators → www/api_connexion}/__init__.py +0 -0
  88. {apache_airflow_providers_fab-2.0.0rc1.dist-info → apache_airflow_providers_fab-2.0.0rc2.dist-info}/entry_points.txt +0 -0
@@ -199,55 +199,3 @@ distributed under the License is distributed on an "AS IS" BASIS,
199
199
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
200
  See the License for the specific language governing permissions and
201
201
  limitations under the License.
202
-
203
- ============================================================================
204
- APACHE AIRFLOW SUBCOMPONENTS:
205
-
206
- The Apache Airflow project contains subcomponents with separate copyright
207
- notices and license terms. Your use of the source code for the these
208
- subcomponents is subject to the terms and conditions of the following
209
- licenses.
210
-
211
-
212
- ========================================================================
213
- Third party Apache 2.0 licenses
214
- ========================================================================
215
-
216
- The following components are provided under the Apache 2.0 License.
217
- See project link for details. The text of each license is also included
218
- at 3rd-party-licenses/LICENSE-[project].txt.
219
-
220
- (ALv2 License) hue v4.3.0 (https://github.com/cloudera/hue/)
221
- (ALv2 License) jqclock v2.3.0 (https://github.com/JohnRDOrazio/jQuery-Clock-Plugin)
222
- (ALv2 License) bootstrap3-typeahead v4.0.2 (https://github.com/bassjobsen/Bootstrap-3-Typeahead)
223
- (ALv2 License) connexion v2.7.0 (https://github.com/zalando/connexion)
224
-
225
- ========================================================================
226
- MIT licenses
227
- ========================================================================
228
-
229
- The following components are provided under the MIT License. See project link for details.
230
- The text of each license is also included at 3rd-party-licenses/LICENSE-[project].txt.
231
-
232
- (MIT License) jquery v3.5.1 (https://jquery.org/license/)
233
- (MIT License) dagre-d3 v0.6.4 (https://github.com/cpettitt/dagre-d3)
234
- (MIT License) bootstrap v3.4.1 (https://github.com/twbs/bootstrap/)
235
- (MIT License) d3-tip v0.9.1 (https://github.com/Caged/d3-tip)
236
- (MIT License) dataTables v1.10.25 (https://datatables.net)
237
- (MIT License) normalize.css v3.0.2 (http://necolas.github.io/normalize.css/)
238
- (MIT License) ElasticMock v1.3.2 (https://github.com/vrcmarcos/elasticmock)
239
- (MIT License) MomentJS v2.24.0 (http://momentjs.com/)
240
- (MIT License) eonasdan-bootstrap-datetimepicker v4.17.49 (https://github.com/eonasdan/bootstrap-datetimepicker/)
241
-
242
- ========================================================================
243
- BSD 3-Clause licenses
244
- ========================================================================
245
- The following components are provided under the BSD 3-Clause license. See project links for details.
246
- The text of each license is also included at 3rd-party-licenses/LICENSE-[project].txt.
247
-
248
- (BSD 3 License) d3 v5.16.0 (https://d3js.org)
249
- (BSD 3 License) d3-shape v2.1.0 (https://github.com/d3/d3-shape)
250
- (BSD 3 License) cgroupspy 0.2.1 (https://github.com/cloudsigma/cgroupspy)
251
-
252
- ========================================================================
253
- See 3rd-party-licenses/LICENSES-ui.txt for packages used in `/airflow/www`
@@ -26,9 +26,9 @@ from flask_appbuilder.const import AUTH_LDAP
26
26
  from flask_login import login_user
27
27
 
28
28
  from airflow.api_fastapi.app import get_auth_manager
29
- from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
30
29
 
31
30
  if TYPE_CHECKING:
31
+ from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
32
32
  from airflow.providers.fab.auth_manager.models import User
33
33
 
34
34
  CLIENT_AUTH: tuple[str, str] | Any | None = None
@@ -45,8 +45,7 @@ def auth_current_user() -> User | None:
45
45
  auth = request.authorization
46
46
  if auth is None or not auth.username or not auth.password:
47
47
  return None
48
-
49
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
48
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
50
49
  user = None
51
50
  if security_manager.auth_type == AUTH_LDAP:
52
51
  user = security_manager.auth_user_ldap(auth.username, auth.password)
@@ -67,4 +66,4 @@ def requires_authentication(function: T):
67
66
  else:
68
67
  return Response("Unauthorized", 401, {"WWW-Authenticate": "Basic"})
69
68
 
70
- return cast(T, decorated)
69
+ return cast("T", decorated)
@@ -28,11 +28,11 @@ from requests_kerberos import HTTPKerberosAuth
28
28
 
29
29
  from airflow.api_fastapi.app import get_auth_manager
30
30
  from airflow.configuration import conf
31
- from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
32
31
  from airflow.utils.net import getfqdn
33
32
 
34
33
  if TYPE_CHECKING:
35
- from airflow.auth.managers.models.base_user import BaseUser
34
+ from airflow.api_fastapi.auth.managers.models.base_user import BaseUser
35
+ from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
36
36
 
37
37
  log = logging.getLogger(__name__)
38
38
 
@@ -115,7 +115,7 @@ T = TypeVar("T", bound=Callable)
115
115
 
116
116
 
117
117
  def find_user(username=None, email=None):
118
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
118
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
119
119
  return security_manager.find_user(username=username, email=email)
120
120
 
121
121
 
@@ -143,4 +143,4 @@ def requires_authentication(function: T, find_user: Callable[[str], BaseUser] |
143
143
  return _forbidden()
144
144
  return _unauthorized()
145
145
 
146
- return cast(T, decorated)
146
+ return cast("T", decorated)
@@ -44,4 +44,4 @@ def requires_authentication(function: T):
44
44
  return Response("Unauthorized", 401, {})
45
45
  return function(*args, **kwargs)
46
46
 
47
- return cast(T, decorated)
47
+ return cast("T", decorated)
@@ -24,9 +24,6 @@ from flask import request
24
24
  from marshmallow import ValidationError
25
25
  from sqlalchemy import asc, desc, func, select
26
26
 
27
- from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound
28
- from airflow.api_connexion.parameters import check_limit, format_parameters
29
- from airflow.api_connexion.security import requires_access_custom_view
30
27
  from airflow.api_fastapi.app import get_auth_manager
31
28
  from airflow.providers.fab.auth_manager.models import Action, Role
32
29
  from airflow.providers.fab.auth_manager.schemas.role_and_permission_schema import (
@@ -36,11 +33,15 @@ from airflow.providers.fab.auth_manager.schemas.role_and_permission_schema impor
36
33
  role_collection_schema,
37
34
  role_schema,
38
35
  )
39
- from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
40
- from airflow.security import permissions
36
+ from airflow.providers.fab.www.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound
37
+ from airflow.providers.fab.www.api_connexion.parameters import check_limit, format_parameters
38
+ from airflow.providers.fab.www.api_connexion.security import requires_access_custom_view
39
+ from airflow.providers.fab.www.security import permissions
41
40
 
42
41
  if TYPE_CHECKING:
43
- from airflow.api_connexion.types import APIResponse, UpdateMask
42
+ from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
43
+ from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
44
+ from airflow.providers.fab.www.api_connexion.types import APIResponse, UpdateMask
44
45
 
45
46
 
46
47
  def _check_action_and_resource(sm: FabAirflowSecurityManagerOverride, perms: list[tuple[str, str]]) -> None:
@@ -59,7 +60,7 @@ def _check_action_and_resource(sm: FabAirflowSecurityManagerOverride, perms: lis
59
60
  @requires_access_custom_view("GET", permissions.RESOURCE_ROLE)
60
61
  def get_role(*, role_name: str) -> APIResponse:
61
62
  """Get role."""
62
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
63
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
63
64
  role = security_manager.find_role(name=role_name)
64
65
  if not role:
65
66
  raise NotFound(title="Role not found", detail=f"Role with name {role_name!r} was not found")
@@ -70,7 +71,7 @@ def get_role(*, role_name: str) -> APIResponse:
70
71
  @format_parameters({"limit": check_limit})
71
72
  def get_roles(*, order_by: str = "name", limit: int, offset: int | None = None) -> APIResponse:
72
73
  """Get roles."""
73
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
74
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
74
75
  session = security_manager.get_session
75
76
  total_entries = session.scalars(select(func.count(Role.id))).one()
76
77
  direction = desc if order_by.startswith("-") else asc
@@ -80,8 +81,7 @@ def get_roles(*, order_by: str = "name", limit: int, offset: int | None = None)
80
81
  allowed_sort_attrs = ["role_id", "name"]
81
82
  if order_by not in allowed_sort_attrs:
82
83
  raise BadRequest(
83
- detail=f"Ordering with '{order_by}' is disallowed or "
84
- f"the attribute does not exist on the model"
84
+ detail=f"Ordering with '{order_by}' is disallowed or the attribute does not exist on the model"
85
85
  )
86
86
 
87
87
  query = select(Role)
@@ -98,7 +98,7 @@ def get_roles(*, order_by: str = "name", limit: int, offset: int | None = None)
98
98
  @format_parameters({"limit": check_limit})
99
99
  def get_permissions(*, limit: int, offset: int | None = None) -> APIResponse:
100
100
  """Get permissions."""
101
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
101
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
102
102
  session = security_manager.get_session
103
103
  total_entries = session.scalars(select(func.count(Action.id))).one()
104
104
  query = select(Action)
@@ -109,7 +109,7 @@ def get_permissions(*, limit: int, offset: int | None = None) -> APIResponse:
109
109
  @requires_access_custom_view("DELETE", permissions.RESOURCE_ROLE)
110
110
  def delete_role(*, role_name: str) -> APIResponse:
111
111
  """Delete a role."""
112
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
112
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
113
113
 
114
114
  role = security_manager.find_role(name=role_name)
115
115
  if not role:
@@ -121,7 +121,7 @@ def delete_role(*, role_name: str) -> APIResponse:
121
121
  @requires_access_custom_view("PUT", permissions.RESOURCE_ROLE)
122
122
  def patch_role(*, role_name: str, update_mask: UpdateMask = None) -> APIResponse:
123
123
  """Update a role."""
124
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
124
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
125
125
  body = request.json
126
126
  try:
127
127
  data = role_schema.load(body)
@@ -154,7 +154,7 @@ def patch_role(*, role_name: str, update_mask: UpdateMask = None) -> APIResponse
154
154
  @requires_access_custom_view("POST", permissions.RESOURCE_ROLE)
155
155
  def post_role() -> APIResponse:
156
156
  """Create a new role."""
157
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
157
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
158
158
  body = request.json
159
159
  try:
160
160
  data = role_schema.load(body)
@@ -25,9 +25,6 @@ from marshmallow import ValidationError
25
25
  from sqlalchemy import asc, desc, func, select
26
26
  from werkzeug.security import generate_password_hash
27
27
 
28
- from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound, Unknown
29
- from airflow.api_connexion.parameters import check_limit, format_parameters
30
- from airflow.api_connexion.security import requires_access_custom_view
31
28
  from airflow.api_fastapi.app import get_auth_manager
32
29
  from airflow.providers.fab.auth_manager.models import User
33
30
  from airflow.providers.fab.auth_manager.schemas.user_schema import (
@@ -36,18 +33,21 @@ from airflow.providers.fab.auth_manager.schemas.user_schema import (
36
33
  user_collection_schema,
37
34
  user_schema,
38
35
  )
39
- from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
40
- from airflow.security import permissions
36
+ from airflow.providers.fab.www.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound, Unknown
37
+ from airflow.providers.fab.www.api_connexion.parameters import check_limit, format_parameters
38
+ from airflow.providers.fab.www.api_connexion.security import requires_access_custom_view
39
+ from airflow.providers.fab.www.security import permissions
41
40
 
42
41
  if TYPE_CHECKING:
43
- from airflow.api_connexion.types import APIResponse, UpdateMask
42
+ from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
44
43
  from airflow.providers.fab.auth_manager.models import Role
44
+ from airflow.providers.fab.www.api_connexion.types import APIResponse, UpdateMask
45
45
 
46
46
 
47
47
  @requires_access_custom_view("GET", permissions.RESOURCE_USER)
48
48
  def get_user(*, username: str) -> APIResponse:
49
49
  """Get a user."""
50
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
50
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
51
51
  user = security_manager.find_user(username=username)
52
52
  if not user:
53
53
  raise NotFound(title="User not found", detail=f"The User with username `{username}` was not found")
@@ -58,7 +58,7 @@ def get_user(*, username: str) -> APIResponse:
58
58
  @format_parameters({"limit": check_limit})
59
59
  def get_users(*, limit: int, order_by: str = "id", offset: str | None = None) -> APIResponse:
60
60
  """Get users."""
61
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
61
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
62
62
  session = security_manager.get_session
63
63
  total_entries = session.execute(select(func.count(User.id))).scalar()
64
64
  direction = desc if order_by.startswith("-") else asc
@@ -76,8 +76,7 @@ def get_users(*, limit: int, order_by: str = "id", offset: str | None = None) ->
76
76
  ]
77
77
  if order_by not in allowed_sort_attrs:
78
78
  raise BadRequest(
79
- detail=f"Ordering with '{order_by}' is disallowed or "
80
- f"the attribute does not exist on the model"
79
+ detail=f"Ordering with '{order_by}' is disallowed or the attribute does not exist on the model"
81
80
  )
82
81
 
83
82
  query = select(User).order_by(direction(getattr(User, order_param))).offset(offset).limit(limit)
@@ -94,7 +93,7 @@ def post_user() -> APIResponse:
94
93
  except ValidationError as e:
95
94
  raise BadRequest(detail=str(e.messages))
96
95
 
97
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
96
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
98
97
  username = data["username"]
99
98
  email = data["email"]
100
99
 
@@ -137,7 +136,7 @@ def patch_user(*, username: str, update_mask: UpdateMask = None) -> APIResponse:
137
136
  except ValidationError as e:
138
137
  raise BadRequest(detail=str(e.messages))
139
138
 
140
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
139
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
141
140
 
142
141
  user = security_manager.find_user(username=username)
143
142
  if user is None:
@@ -201,7 +200,7 @@ def patch_user(*, username: str, update_mask: UpdateMask = None) -> APIResponse:
201
200
  @requires_access_custom_view("DELETE", permissions.RESOURCE_USER)
202
201
  def delete_user(*, username: str) -> APIResponse:
203
202
  """Delete a user."""
204
- security_manager = cast(FabAirflowSecurityManagerOverride, get_auth_manager().security_manager)
203
+ security_manager = cast("FabAuthManager", get_auth_manager()).security_manager
205
204
 
206
205
  user = security_manager.find_user(username=username)
207
206
  if user is None:
@@ -0,0 +1,16 @@
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.
@@ -0,0 +1,16 @@
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.
@@ -0,0 +1,32 @@
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 airflow.api_fastapi.core_api.base import BaseModel
20
+
21
+
22
+ class LoginResponse(BaseModel):
23
+ """API Token serializer for responses."""
24
+
25
+ access_token: str
26
+
27
+
28
+ class LoginBody(BaseModel):
29
+ """API Token serializer for requests."""
30
+
31
+ username: str
32
+ password: str
@@ -0,0 +1,16 @@
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.
@@ -0,0 +1,153 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: FAB auth manager API
4
+ description: This is FAB auth manager API. This API is only available if the auth
5
+ manager used in the Airflow environment is FAB auth manager. This API provides
6
+ endpoints to manage users and permissions managed by the FAB auth manager.
7
+ version: 0.1.0
8
+ paths:
9
+ /token:
10
+ post:
11
+ tags:
12
+ - FabAuthManager
13
+ summary: Create Token
14
+ description: Generate a new API token.
15
+ operationId: create_token
16
+ requestBody:
17
+ content:
18
+ application/json:
19
+ schema:
20
+ $ref: '#/components/schemas/LoginBody'
21
+ required: true
22
+ responses:
23
+ '201':
24
+ description: Successful Response
25
+ content:
26
+ application/json:
27
+ schema:
28
+ $ref: '#/components/schemas/LoginResponse'
29
+ '400':
30
+ description: Bad Request
31
+ content:
32
+ application/json:
33
+ schema:
34
+ $ref: '#/components/schemas/HTTPExceptionResponse'
35
+ '401':
36
+ description: Unauthorized
37
+ content:
38
+ application/json:
39
+ schema:
40
+ $ref: '#/components/schemas/HTTPExceptionResponse'
41
+ '422':
42
+ description: Validation Error
43
+ content:
44
+ application/json:
45
+ schema:
46
+ $ref: '#/components/schemas/HTTPValidationError'
47
+ /token/cli:
48
+ post:
49
+ tags:
50
+ - FabAuthManager
51
+ summary: Create Token Cli
52
+ description: Generate a new CLI API token.
53
+ operationId: create_token_cli
54
+ requestBody:
55
+ content:
56
+ application/json:
57
+ schema:
58
+ $ref: '#/components/schemas/LoginBody'
59
+ required: true
60
+ responses:
61
+ '201':
62
+ description: Successful Response
63
+ content:
64
+ application/json:
65
+ schema:
66
+ $ref: '#/components/schemas/LoginResponse'
67
+ '400':
68
+ description: Bad Request
69
+ content:
70
+ application/json:
71
+ schema:
72
+ $ref: '#/components/schemas/HTTPExceptionResponse'
73
+ '401':
74
+ description: Unauthorized
75
+ content:
76
+ application/json:
77
+ schema:
78
+ $ref: '#/components/schemas/HTTPExceptionResponse'
79
+ '422':
80
+ description: Validation Error
81
+ content:
82
+ application/json:
83
+ schema:
84
+ $ref: '#/components/schemas/HTTPValidationError'
85
+ components:
86
+ schemas:
87
+ HTTPExceptionResponse:
88
+ properties:
89
+ detail:
90
+ anyOf:
91
+ - type: string
92
+ - additionalProperties: true
93
+ type: object
94
+ title: Detail
95
+ type: object
96
+ required:
97
+ - detail
98
+ title: HTTPExceptionResponse
99
+ description: HTTPException Model used for error response.
100
+ HTTPValidationError:
101
+ properties:
102
+ detail:
103
+ items:
104
+ $ref: '#/components/schemas/ValidationError'
105
+ type: array
106
+ title: Detail
107
+ type: object
108
+ title: HTTPValidationError
109
+ LoginBody:
110
+ properties:
111
+ username:
112
+ type: string
113
+ title: Username
114
+ password:
115
+ type: string
116
+ title: Password
117
+ type: object
118
+ required:
119
+ - username
120
+ - password
121
+ title: LoginBody
122
+ description: API Token serializer for requests.
123
+ LoginResponse:
124
+ properties:
125
+ access_token:
126
+ type: string
127
+ title: Access Token
128
+ type: object
129
+ required:
130
+ - access_token
131
+ title: LoginResponse
132
+ description: API Token serializer for responses.
133
+ ValidationError:
134
+ properties:
135
+ loc:
136
+ items:
137
+ anyOf:
138
+ - type: string
139
+ - type: integer
140
+ type: array
141
+ title: Location
142
+ msg:
143
+ type: string
144
+ title: Message
145
+ type:
146
+ type: string
147
+ title: Error Type
148
+ type: object
149
+ required:
150
+ - loc
151
+ - msg
152
+ - type
153
+ title: ValidationError
@@ -0,0 +1,16 @@
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.
@@ -0,0 +1,51 @@
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 starlette import status
20
+
21
+ from airflow.api_fastapi.common.router import AirflowRouter
22
+ from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
23
+ from airflow.configuration import conf
24
+ from airflow.providers.fab.auth_manager.api_fastapi.datamodels.login import LoginBody, LoginResponse
25
+ from airflow.providers.fab.auth_manager.api_fastapi.services.login import FABAuthManagerLogin
26
+
27
+ login_router = AirflowRouter(tags=["FabAuthManager"])
28
+
29
+
30
+ @login_router.post(
31
+ "/token",
32
+ response_model=LoginResponse,
33
+ status_code=status.HTTP_201_CREATED,
34
+ responses=create_openapi_http_exception_doc([status.HTTP_400_BAD_REQUEST, status.HTTP_401_UNAUTHORIZED]),
35
+ )
36
+ def create_token(body: LoginBody) -> LoginResponse:
37
+ """Generate a new API token."""
38
+ return FABAuthManagerLogin.create_token(body=body)
39
+
40
+
41
+ @login_router.post(
42
+ "/token/cli",
43
+ response_model=LoginResponse,
44
+ status_code=status.HTTP_201_CREATED,
45
+ responses=create_openapi_http_exception_doc([status.HTTP_400_BAD_REQUEST, status.HTTP_401_UNAUTHORIZED]),
46
+ )
47
+ def create_token_cli(body: LoginBody) -> LoginResponse:
48
+ """Generate a new CLI API token."""
49
+ return FABAuthManagerLogin.create_token(
50
+ body=body, expiration_time_in_seconds=conf.getint("api_auth", "jwt_cli_expiration_time")
51
+ )
@@ -0,0 +1,16 @@
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.