apache-airflow-providers-fab 1.4.1__tar.gz → 1.5.0__tar.gz

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 (50) hide show
  1. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/PKG-INFO +10 -10
  2. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/README.rst +5 -5
  3. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/__init__.py +1 -1
  4. apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/api/auth/backend/session.py +47 -0
  5. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api_endpoints/role_and_permission_endpoint.py +3 -3
  6. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api_endpoints/user_endpoint.py +3 -3
  7. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/fab_auth_manager.py +13 -5
  8. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/models/db.py +4 -5
  9. apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/schemas/role_and_permission_schema.py +103 -0
  10. apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/schemas/user_schema.py +73 -0
  11. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/security_manager/override.py +14 -10
  12. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/get_provider_info.py +4 -3
  13. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/env.py +2 -1
  14. apache_airflow_providers_fab-1.5.0/airflow/providers/fab/migrations/versions/__init__.py +16 -0
  15. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/pyproject.toml +6 -6
  16. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/LICENSE +0 -0
  17. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/alembic.ini +0 -0
  18. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/__init__.py +0 -0
  19. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/__init__.py +0 -0
  20. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/auth/__init__.py +0 -0
  21. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/auth/backend/__init__.py +0 -0
  22. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/auth/backend/basic_auth.py +0 -0
  23. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/auth/backend/kerberos_auth.py +0 -0
  24. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api_endpoints/__init__.py +0 -0
  25. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/__init__.py +0 -0
  26. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/db_command.py +0 -0
  27. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/definition.py +0 -0
  28. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/role_command.py +0 -0
  29. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/sync_perm_command.py +0 -0
  30. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/user_command.py +0 -0
  31. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/cli_commands/utils.py +0 -0
  32. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/decorators/__init__.py +0 -0
  33. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/decorators/auth.py +0 -0
  34. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/models/__init__.py +0 -0
  35. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/models/anonymous_user.py +0 -0
  36. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/openapi/__init__.py +0 -0
  37. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/openapi/v1.yaml +0 -0
  38. {apache_airflow_providers_fab-1.4.1/airflow/providers/fab/auth_manager/views → apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/schemas}/__init__.py +0 -0
  39. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/security_manager/__init__.py +0 -0
  40. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/security_manager/constants.py +0 -0
  41. {apache_airflow_providers_fab-1.4.1/airflow/providers/fab/migrations → apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/views}/__init__.py +0 -0
  42. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/permissions.py +0 -0
  43. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/roles_list.py +0 -0
  44. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/user.py +0 -0
  45. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/user_edit.py +0 -0
  46. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/user_stats.py +0 -0
  47. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/README +0 -0
  48. {apache_airflow_providers_fab-1.4.1/airflow/providers/fab/migrations/versions → apache_airflow_providers_fab-1.5.0/airflow/providers/fab/migrations}/__init__.py +0 -0
  49. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/script.py.mako +0 -0
  50. {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/versions/0001_1_4_0_placeholder_migration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apache-airflow-providers-fab
3
- Version: 1.4.1
3
+ Version: 1.5.0
4
4
  Summary: Provider package apache-airflow-providers-fab for Apache Airflow
5
5
  Keywords: airflow-provider,fab,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
@@ -20,9 +20,9 @@ Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Topic :: System :: Monitoring
23
- Requires-Dist: apache-airflow-providers-common-compat>=1.2.0
23
+ Requires-Dist: apache-airflow-providers-common-compat>=1.2.1
24
24
  Requires-Dist: apache-airflow>=2.9.0
25
- Requires-Dist: flask-appbuilder==4.5.0
25
+ Requires-Dist: flask-appbuilder==4.5.2
26
26
  Requires-Dist: flask-login>=0.6.2
27
27
  Requires-Dist: flask>=2.2,<2.3
28
28
  Requires-Dist: google-re2>=1.0
@@ -30,8 +30,8 @@ Requires-Dist: jmespath>=0.7.0
30
30
  Requires-Dist: apache-airflow-providers-common-compat ; extra == "common.compat"
31
31
  Requires-Dist: kerberos>=1.3.0 ; extra == "kerberos"
32
32
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
33
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/changelog.html
34
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1
33
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/changelog.html
34
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0
35
35
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
36
36
  Project-URL: Source Code, https://github.com/apache/airflow
37
37
  Project-URL: Twitter, https://twitter.com/ApacheAirflow
@@ -83,7 +83,7 @@ Provides-Extra: kerberos
83
83
 
84
84
  Package ``apache-airflow-providers-fab``
85
85
 
86
- Release: ``1.4.1``
86
+ Release: ``1.5.0``
87
87
 
88
88
 
89
89
  `Flask App Builder <https://flask-appbuilder.readthedocs.io/>`__
@@ -96,7 +96,7 @@ This is a provider package for ``fab`` provider. All classes for this provider p
96
96
  are in ``airflow.providers.fab`` python package.
97
97
 
98
98
  You can find package information and changelog for the provider
99
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/>`_.
99
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/>`_.
100
100
 
101
101
  Installation
102
102
  ------------
@@ -114,9 +114,9 @@ Requirements
114
114
  PIP package Version required
115
115
  ========================================== ==================
116
116
  ``apache-airflow`` ``>=2.9.0``
117
- ``apache-airflow-providers-common-compat`` ``>=1.2.0``
117
+ ``apache-airflow-providers-common-compat`` ``>=1.2.1``
118
118
  ``flask`` ``>=2.2,<2.3``
119
- ``flask-appbuilder`` ``==4.5.0``
119
+ ``flask-appbuilder`` ``==4.5.2``
120
120
  ``flask-login`` ``>=0.6.2``
121
121
  ``google-re2`` ``>=1.0``
122
122
  ``jmespath`` ``>=0.7.0``
@@ -142,4 +142,4 @@ Dependent package
142
142
  ================================================================================================================== =================
143
143
 
144
144
  The changelog for the provider package can be found in the
145
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/changelog.html>`_.
145
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/changelog.html>`_.
@@ -42,7 +42,7 @@
42
42
 
43
43
  Package ``apache-airflow-providers-fab``
44
44
 
45
- Release: ``1.4.1``
45
+ Release: ``1.5.0``
46
46
 
47
47
 
48
48
  `Flask App Builder <https://flask-appbuilder.readthedocs.io/>`__
@@ -55,7 +55,7 @@ This is a provider package for ``fab`` provider. All classes for this provider p
55
55
  are in ``airflow.providers.fab`` python package.
56
56
 
57
57
  You can find package information and changelog for the provider
58
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/>`_.
58
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/>`_.
59
59
 
60
60
  Installation
61
61
  ------------
@@ -73,9 +73,9 @@ Requirements
73
73
  PIP package Version required
74
74
  ========================================== ==================
75
75
  ``apache-airflow`` ``>=2.9.0``
76
- ``apache-airflow-providers-common-compat`` ``>=1.2.0``
76
+ ``apache-airflow-providers-common-compat`` ``>=1.2.1``
77
77
  ``flask`` ``>=2.2,<2.3``
78
- ``flask-appbuilder`` ``==4.5.0``
78
+ ``flask-appbuilder`` ``==4.5.2``
79
79
  ``flask-login`` ``>=0.6.2``
80
80
  ``google-re2`` ``>=1.0``
81
81
  ``jmespath`` ``>=0.7.0``
@@ -101,4 +101,4 @@ Dependent package
101
101
  ================================================================================================================== =================
102
102
 
103
103
  The changelog for the provider package can be found in the
104
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/changelog.html>`_.
104
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/changelog.html>`_.
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "1.4.1"
32
+ __version__ = "1.5.0"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.9.0"
@@ -0,0 +1,47 @@
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
+ """Session authentication backend."""
18
+
19
+ from __future__ import annotations
20
+
21
+ from functools import wraps
22
+ from typing import Any, Callable, TypeVar, cast
23
+
24
+ from flask import Response
25
+
26
+ from airflow.www.extensions.init_auth_manager import get_auth_manager
27
+
28
+ CLIENT_AUTH: tuple[str, str] | Any | None = None
29
+
30
+
31
+ def init_app(_):
32
+ """Initialize authentication backend."""
33
+
34
+
35
+ T = TypeVar("T", bound=Callable)
36
+
37
+
38
+ def requires_authentication(function: T):
39
+ """Decorate functions that require authentication."""
40
+
41
+ @wraps(function)
42
+ def decorated(*args, **kwargs):
43
+ if not get_auth_manager().is_logged_in():
44
+ return Response("Unauthorized", 401, {})
45
+ return function(*args, **kwargs)
46
+
47
+ return cast(T, decorated)
@@ -26,15 +26,15 @@ from sqlalchemy import asc, desc, func, select
26
26
 
27
27
  from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound
28
28
  from airflow.api_connexion.parameters import check_limit, format_parameters
29
- from airflow.api_connexion.schemas.role_and_permission_schema import (
29
+ from airflow.api_connexion.security import requires_access_custom_view
30
+ from airflow.providers.fab.auth_manager.models import Action, Role
31
+ from airflow.providers.fab.auth_manager.schemas.role_and_permission_schema import (
30
32
  ActionCollection,
31
33
  RoleCollection,
32
34
  action_collection_schema,
33
35
  role_collection_schema,
34
36
  role_schema,
35
37
  )
36
- from airflow.api_connexion.security import requires_access_custom_view
37
- from airflow.providers.fab.auth_manager.models import Action, Role
38
38
  from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
39
39
  from airflow.security import permissions
40
40
  from airflow.www.extensions.init_auth_manager import get_auth_manager
@@ -27,14 +27,14 @@ from werkzeug.security import generate_password_hash
27
27
 
28
28
  from airflow.api_connexion.exceptions import AlreadyExists, BadRequest, NotFound, Unknown
29
29
  from airflow.api_connexion.parameters import check_limit, format_parameters
30
- from airflow.api_connexion.schemas.user_schema import (
30
+ from airflow.api_connexion.security import requires_access_custom_view
31
+ from airflow.providers.fab.auth_manager.models import User
32
+ from airflow.providers.fab.auth_manager.schemas.user_schema import (
31
33
  UserCollection,
32
34
  user_collection_item_schema,
33
35
  user_collection_schema,
34
36
  user_schema,
35
37
  )
36
- from airflow.api_connexion.security import requires_access_custom_view
37
- from airflow.providers.fab.auth_manager.models import User
38
38
  from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
39
39
  from airflow.security import permissions
40
40
  from airflow.www.extensions.init_auth_manager import get_auth_manager
@@ -18,6 +18,7 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import argparse
21
+ import warnings
21
22
  from functools import cached_property
22
23
  from pathlib import Path
23
24
  from typing import TYPE_CHECKING, Container
@@ -46,7 +47,7 @@ from airflow.cli.cli_config import (
46
47
  GroupCommand,
47
48
  )
48
49
  from airflow.configuration import conf
49
- from airflow.exceptions import AirflowConfigException, AirflowException
50
+ from airflow.exceptions import AirflowConfigException, AirflowException, AirflowProviderDeprecationWarning
50
51
  from airflow.models import DagModel
51
52
  from airflow.providers.fab.auth_manager.cli_commands.definition import (
52
53
  DB_COMMANDS,
@@ -96,10 +97,7 @@ if TYPE_CHECKING:
96
97
  from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
97
98
  from airflow.security.permissions import RESOURCE_ASSET
98
99
  else:
99
- try:
100
- from airflow.security.permissions import RESOURCE_ASSET
101
- except ImportError:
102
- from airflow.security.permissions import RESOURCE_DATASET as RESOURCE_ASSET
100
+ from airflow.providers.common.compat.security.permissions import RESOURCE_ASSET
103
101
 
104
102
 
105
103
  _MAP_DAG_ACCESS_ENTITY_TO_FAB_RESOURCE_TYPE: dict[DagAccessEntity, tuple[str, ...]] = {
@@ -274,6 +272,16 @@ class FabAuthManager(BaseAuthManager):
274
272
  ) -> bool:
275
273
  return self._is_authorized(method=method, resource_type=RESOURCE_ASSET, user=user)
276
274
 
275
+ def is_authorized_dataset(
276
+ self, *, method: ResourceMethod, details: AssetDetails | None = None, user: BaseUser | None = None
277
+ ) -> bool:
278
+ warnings.warn(
279
+ "is_authorized_dataset will be renamed as is_authorized_asset in Airflow 3 and will be removed when the minimum Airflow version is set to 3.0 for the fab provider",
280
+ AirflowProviderDeprecationWarning,
281
+ stacklevel=2,
282
+ )
283
+ return self.is_authorized_asset(method=method, user=user)
284
+
277
285
  def is_authorized_pool(
278
286
  self, *, method: ResourceMethod, details: PoolDetails | None = None, user: BaseUser | None = None
279
287
  ) -> bool:
@@ -16,16 +16,15 @@
16
16
  # under the License.
17
17
  from __future__ import annotations
18
18
 
19
- import os
19
+ from pathlib import Path
20
20
 
21
- import airflow
22
21
  from airflow import settings
23
22
  from airflow.exceptions import AirflowException
24
23
  from airflow.providers.fab.auth_manager.models import metadata
25
24
  from airflow.utils.db import _offline_migration, print_happy_cat
26
25
  from airflow.utils.db_manager import BaseDBManager
27
26
 
28
- PACKAGE_DIR = os.path.dirname(airflow.__file__)
27
+ PACKAGE_DIR = Path(__file__).parents[2]
29
28
 
30
29
  _REVISION_HEADS_MAP: dict[str, str] = {
31
30
  "1.4.0": "6709f7a774b9",
@@ -37,8 +36,8 @@ class FABDBManager(BaseDBManager):
37
36
 
38
37
  metadata = metadata
39
38
  version_table_name = "alembic_version_fab"
40
- migration_dir = os.path.join(PACKAGE_DIR, "providers/fab/migrations")
41
- alembic_file = os.path.join(PACKAGE_DIR, "providers/fab/alembic.ini")
39
+ migration_dir = (PACKAGE_DIR / "migrations").as_posix()
40
+ alembic_file = (PACKAGE_DIR / "alembic.ini").as_posix()
42
41
  supports_table_dropping = True
43
42
 
44
43
  def upgradedb(self, to_revision=None, from_revision=None, show_sql_only=False):
@@ -0,0 +1,103 @@
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 typing import NamedTuple
20
+
21
+ from marshmallow import Schema, fields
22
+ from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
23
+
24
+ from airflow.providers.fab.auth_manager.models import Action, Permission, Resource, Role
25
+
26
+
27
+ class ActionSchema(SQLAlchemySchema):
28
+ """Action Schema."""
29
+
30
+ class Meta:
31
+ """Meta."""
32
+
33
+ model = Action
34
+
35
+ name = auto_field()
36
+
37
+
38
+ class ResourceSchema(SQLAlchemySchema):
39
+ """View menu Schema."""
40
+
41
+ class Meta:
42
+ """Meta."""
43
+
44
+ model = Resource
45
+
46
+ name = auto_field()
47
+
48
+
49
+ class ActionCollection(NamedTuple):
50
+ """Action Collection."""
51
+
52
+ actions: list[Action]
53
+ total_entries: int
54
+
55
+
56
+ class ActionCollectionSchema(Schema):
57
+ """Permissions list schema."""
58
+
59
+ actions = fields.List(fields.Nested(ActionSchema))
60
+ total_entries = fields.Int()
61
+
62
+
63
+ class ActionResourceSchema(SQLAlchemySchema):
64
+ """Action View Schema."""
65
+
66
+ class Meta:
67
+ """Meta."""
68
+
69
+ model = Permission
70
+
71
+ action = fields.Nested(ActionSchema, data_key="action")
72
+ resource = fields.Nested(ResourceSchema, data_key="resource")
73
+
74
+
75
+ class RoleSchema(SQLAlchemySchema):
76
+ """Role item schema."""
77
+
78
+ class Meta:
79
+ """Meta."""
80
+
81
+ model = Role
82
+
83
+ name = auto_field()
84
+ permissions = fields.List(fields.Nested(ActionResourceSchema), data_key="actions")
85
+
86
+
87
+ class RoleCollection(NamedTuple):
88
+ """List of roles."""
89
+
90
+ roles: list[Role]
91
+ total_entries: int
92
+
93
+
94
+ class RoleCollectionSchema(Schema):
95
+ """List of roles."""
96
+
97
+ roles = fields.List(fields.Nested(RoleSchema))
98
+ total_entries = fields.Int()
99
+
100
+
101
+ role_schema = RoleSchema()
102
+ role_collection_schema = RoleCollectionSchema()
103
+ action_collection_schema = ActionCollectionSchema()
@@ -0,0 +1,73 @@
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 typing import NamedTuple
20
+
21
+ from marshmallow import Schema, fields
22
+ from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
23
+
24
+ from airflow.api_connexion.parameters import validate_istimezone
25
+ from airflow.providers.fab.auth_manager.models import User
26
+ from airflow.providers.fab.auth_manager.schemas.role_and_permission_schema import RoleSchema
27
+
28
+
29
+ class UserCollectionItemSchema(SQLAlchemySchema):
30
+ """user collection item schema."""
31
+
32
+ class Meta:
33
+ """Meta."""
34
+
35
+ model = User
36
+ dateformat = "iso"
37
+
38
+ first_name = auto_field()
39
+ last_name = auto_field()
40
+ username = auto_field()
41
+ active = auto_field(dump_only=True)
42
+ email = auto_field()
43
+ last_login = auto_field(dump_only=True)
44
+ login_count = auto_field(dump_only=True)
45
+ fail_login_count = auto_field(dump_only=True)
46
+ roles = fields.List(fields.Nested(RoleSchema, only=("name",)))
47
+ created_on = auto_field(validate=validate_istimezone, dump_only=True)
48
+ changed_on = auto_field(validate=validate_istimezone, dump_only=True)
49
+
50
+
51
+ class UserSchema(UserCollectionItemSchema):
52
+ """User schema."""
53
+
54
+ password = auto_field(load_only=True)
55
+
56
+
57
+ class UserCollection(NamedTuple):
58
+ """User collection."""
59
+
60
+ users: list[User]
61
+ total_entries: int
62
+
63
+
64
+ class UserCollectionSchema(Schema):
65
+ """User collection schema."""
66
+
67
+ users = fields.List(fields.Nested(UserCollectionItemSchema))
68
+ total_entries = fields.Int()
69
+
70
+
71
+ user_collection_item_schema = UserCollectionItemSchema()
72
+ user_schema = UserSchema()
73
+ user_collection_schema = UserCollectionSchema()
@@ -17,6 +17,7 @@
17
17
  # under the License.
18
18
  from __future__ import annotations
19
19
 
20
+ import copy
20
21
  import datetime
21
22
  import itertools
22
23
  import logging
@@ -24,7 +25,7 @@ import os
24
25
  import random
25
26
  import uuid
26
27
  import warnings
27
- from typing import TYPE_CHECKING, Any, Callable, Collection, Container, Iterable, Sequence
28
+ from typing import TYPE_CHECKING, Any, Callable, Collection, Container, Iterable, Mapping, Sequence
28
29
 
29
30
  import jwt
30
31
  import packaging.version
@@ -117,10 +118,7 @@ if TYPE_CHECKING:
117
118
  from airflow.auth.managers.base_auth_manager import ResourceMethod
118
119
  from airflow.security.permissions import RESOURCE_ASSET
119
120
  else:
120
- try:
121
- from airflow.security.permissions import RESOURCE_ASSET
122
- except ImportError:
123
- from airflow.security.permissions import RESOURCE_DATASET as RESOURCE_ASSET
121
+ from airflow.providers.common.compat.security.permissions import RESOURCE_ASSET
124
122
 
125
123
  log = logging.getLogger(__name__)
126
124
 
@@ -1110,7 +1108,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1110
1108
  def sync_perm_for_dag(
1111
1109
  self,
1112
1110
  dag_id: str,
1113
- access_control: dict[str, dict[str, Collection[str]]] | None = None,
1111
+ access_control: Mapping[str, Mapping[str, Collection[str]] | Collection[str]] | None = None,
1114
1112
  ) -> None:
1115
1113
  """
1116
1114
  Sync permissions for given dag id.
@@ -1131,7 +1129,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1131
1129
 
1132
1130
  if access_control is not None:
1133
1131
  self.log.debug("Syncing DAG-level permissions for DAG '%s'", dag_id)
1134
- self._sync_dag_view_permissions(dag_id, access_control.copy())
1132
+ self._sync_dag_view_permissions(dag_id, copy.copy(access_control))
1135
1133
  else:
1136
1134
  self.log.debug(
1137
1135
  "Not syncing DAG-level permissions for DAG '%s' as access control is unset.",
@@ -1152,7 +1150,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1152
1150
  def _sync_dag_view_permissions(
1153
1151
  self,
1154
1152
  dag_id: str,
1155
- access_control: dict[str, dict[str, Collection[str]]],
1153
+ access_control: Mapping[str, Mapping[str, Collection[str]] | Collection[str]],
1156
1154
  ) -> None:
1157
1155
  """
1158
1156
  Set the access policy on the given DAG's ViewModel.
@@ -1178,7 +1176,13 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1178
1176
  for perm in existing_dag_perms:
1179
1177
  non_admin_roles = [role for role in perm.role if role.name != "Admin"]
1180
1178
  for role in non_admin_roles:
1181
- target_perms_for_role = access_control.get(role.name, {}).get(resource_name, set())
1179
+ access_control_role = access_control.get(role.name)
1180
+ target_perms_for_role = set()
1181
+ if access_control_role:
1182
+ if isinstance(access_control_role, set):
1183
+ target_perms_for_role = access_control_role
1184
+ elif isinstance(access_control_role, dict):
1185
+ target_perms_for_role = access_control_role.get(resource_name, set())
1182
1186
  if perm.action.name not in target_perms_for_role:
1183
1187
  self.log.info(
1184
1188
  "Revoking '%s' on DAG '%s' for role '%s'",
@@ -1197,7 +1201,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1197
1201
  f"'{rolename}', but that role does not exist"
1198
1202
  )
1199
1203
 
1200
- if isinstance(resource_actions, (set, list)):
1204
+ if not isinstance(resource_actions, dict):
1201
1205
  # Support for old-style access_control where only the actions are specified
1202
1206
  resource_actions = {permissions.RESOURCE_DAG: set(resource_actions)}
1203
1207
 
@@ -28,8 +28,9 @@ def get_provider_info():
28
28
  "name": "Fab",
29
29
  "description": "`Flask App Builder <https://flask-appbuilder.readthedocs.io/>`__\n",
30
30
  "state": "ready",
31
- "source-date-epoch": 1728485088,
31
+ "source-date-epoch": 1730012648,
32
32
  "versions": [
33
+ "1.5.0",
33
34
  "1.4.1",
34
35
  "1.4.0",
35
36
  "1.3.0",
@@ -46,9 +47,9 @@ def get_provider_info():
46
47
  ],
47
48
  "dependencies": [
48
49
  "apache-airflow>=2.9.0",
49
- "apache-airflow-providers-common-compat>=1.2.0",
50
+ "apache-airflow-providers-common-compat>=1.2.1",
50
51
  "flask>=2.2,<2.3",
51
- "flask-appbuilder==4.5.0",
52
+ "flask-appbuilder==4.5.2",
52
53
  "flask-login>=0.6.2",
53
54
  "google-re2>=1.0",
54
55
  "jmespath>=0.7.0",
@@ -17,6 +17,7 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import contextlib
20
+ from logging import getLogger
20
21
  from logging.config import fileConfig
21
22
 
22
23
  from alembic import context
@@ -32,7 +33,7 @@ version_table = FABDBManager.version_table_name
32
33
 
33
34
  # Interpret the config file for Python logging.
34
35
  # This line sets up loggers basically.
35
- if config.config_file_name is not None:
36
+ if not getLogger().handlers and config.config_file_name:
36
37
  fileConfig(config.config_file_name, disable_existing_loggers=False)
37
38
 
38
39
  # add your model's MetaData object here
@@ -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.
@@ -23,12 +23,12 @@
23
23
  # `pyproject_TEMPLATE.toml.jinja2` IN the `dev/breeze/src/airflow_breeze/templates` DIRECTORY
24
24
  #
25
25
  [build-system]
26
- requires = ["flit_core >=3.2,<4"]
26
+ requires = ["flit_core==3.10.0"]
27
27
  build-backend = "flit_core.buildapi"
28
28
 
29
29
  [project]
30
30
  name = "apache-airflow-providers-fab"
31
- version = "1.4.1"
31
+ version = "1.5.0"
32
32
  description = "Provider package apache-airflow-providers-fab for Apache Airflow"
33
33
  readme = "README.rst"
34
34
  authors = [
@@ -55,9 +55,9 @@ classifiers = [
55
55
  ]
56
56
  requires-python = "~=3.9"
57
57
  dependencies = [
58
- "apache-airflow-providers-common-compat>=1.2.0",
58
+ "apache-airflow-providers-common-compat>=1.2.1",
59
59
  "apache-airflow>=2.9.0",
60
- "flask-appbuilder==4.5.0",
60
+ "flask-appbuilder==4.5.2",
61
61
  "flask-login>=0.6.2",
62
62
  "flask>=2.2,<2.3",
63
63
  "google-re2>=1.0",
@@ -65,8 +65,8 @@ dependencies = [
65
65
  ]
66
66
 
67
67
  [project.urls]
68
- "Documentation" = "https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1"
69
- "Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-fab/1.4.1/changelog.html"
68
+ "Documentation" = "https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0"
69
+ "Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-fab/1.5.0/changelog.html"
70
70
  "Bug Tracker" = "https://github.com/apache/airflow/issues"
71
71
  "Source Code" = "https://github.com/apache/airflow"
72
72
  "Slack Chat" = "https://s.apache.org/airflow-slack"