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.
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/PKG-INFO +10 -10
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/README.rst +5 -5
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/__init__.py +1 -1
- apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/api/auth/backend/session.py +47 -0
- {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
- {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
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/models/db.py +4 -5
- apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/schemas/role_and_permission_schema.py +103 -0
- apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/schemas/user_schema.py +73 -0
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/get_provider_info.py +4 -3
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/env.py +2 -1
- apache_airflow_providers_fab-1.5.0/airflow/providers/fab/migrations/versions/__init__.py +16 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/pyproject.toml +6 -6
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/LICENSE +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/alembic.ini +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/__init__.py +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/api/__init__.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/decorators/__init__.py +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/decorators/auth.py +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/models/__init__.py +0 -0
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/openapi/__init__.py +0 -0
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/openapi/v1.yaml +0 -0
- {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
- {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
- {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
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/permissions.py +0 -0
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/auth_manager/views/user.py +0 -0
- {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
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/README +0 -0
- {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
- {apache_airflow_providers_fab-1.4.1 → apache_airflow_providers_fab-1.5.0}/airflow/providers/fab/migrations/script.py.mako +0 -0
- {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.
|
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.
|
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.
|
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.
|
34
|
-
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-fab/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.
|
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.
|
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.
|
117
|
+
``apache-airflow-providers-common-compat`` ``>=1.2.1``
|
118
118
|
``flask`` ``>=2.2,<2.3``
|
119
|
-
``flask-appbuilder`` ``==4.5.
|
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.
|
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.
|
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.
|
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.
|
76
|
+
``apache-airflow-providers-common-compat`` ``>=1.2.1``
|
77
77
|
``flask`` ``>=2.2,<2.3``
|
78
|
-
``flask-appbuilder`` ``==4.5.
|
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.
|
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.
|
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"
|
apache_airflow_providers_fab-1.5.0/airflow/providers/fab/auth_manager/api/auth/backend/session.py
ADDED
@@ -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.
|
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.
|
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
|
-
|
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
|
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 =
|
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 =
|
41
|
-
alembic_file =
|
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
|
-
|
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:
|
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,
|
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:
|
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
|
-
|
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,
|
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":
|
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.
|
50
|
+
"apache-airflow-providers-common-compat>=1.2.1",
|
50
51
|
"flask>=2.2,<2.3",
|
51
|
-
"flask-appbuilder==4.5.
|
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
|
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
|
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.
|
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.
|
58
|
+
"apache-airflow-providers-common-compat>=1.2.1",
|
59
59
|
"apache-airflow>=2.9.0",
|
60
|
-
"flask-appbuilder==4.5.
|
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.
|
69
|
-
"Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-fab/1.
|
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"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|