apache-airflow-providers-fab 1.2.2rc1__py3-none-any.whl → 1.3.0__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.
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "1.2.2"
32
+ __version__ = "1.3.0"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.9.0"
@@ -61,7 +61,6 @@ from airflow.security.permissions import (
61
61
  RESOURCE_DAG,
62
62
  RESOURCE_DAG_CODE,
63
63
  RESOURCE_DAG_DEPENDENCIES,
64
- RESOURCE_DAG_PREFIX,
65
64
  RESOURCE_DAG_RUN,
66
65
  RESOURCE_DAG_WARNING,
67
66
  RESOURCE_DATASET,
@@ -242,6 +241,8 @@ class FabAuthManager(BaseAuthManager):
242
241
 
243
242
  return all(
244
243
  self._is_authorized(method=method, resource_type=resource_type, user=user)
244
+ if resource_type != RESOURCE_DAG_RUN or not hasattr(permissions, "resource_name")
245
+ else self._is_authorized_dag_run(method=method, details=details, user=user)
245
246
  for resource_type in resource_types
246
247
  )
247
248
 
@@ -412,7 +413,33 @@ class FabAuthManager(BaseAuthManager):
412
413
 
413
414
  if details and details.id:
414
415
  # Check whether the user has permissions to access a specific DAG
415
- resource_dag_name = self._resource_name_for_dag(details.id)
416
+ resource_dag_name = self._resource_name(details.id, RESOURCE_DAG)
417
+ return self._is_authorized(method=method, resource_type=resource_dag_name, user=user)
418
+
419
+ return False
420
+
421
+ def _is_authorized_dag_run(
422
+ self,
423
+ method: ResourceMethod,
424
+ details: DagDetails | None = None,
425
+ user: BaseUser | None = None,
426
+ ) -> bool:
427
+ """
428
+ Return whether the user is authorized to perform a given action on a DAG Run.
429
+
430
+ :param method: the method to perform
431
+ :param details: optional, details about the DAG
432
+ :param user: optional, the user to perform the action on. If not provided, it uses the current user
433
+
434
+ :meta private:
435
+ """
436
+ is_global_authorized = self._is_authorized(method=method, resource_type=RESOURCE_DAG_RUN, user=user)
437
+ if is_global_authorized:
438
+ return True
439
+
440
+ if details and details.id:
441
+ # Check whether the user has permissions to access a specific DAG Run permission on a DAG Level
442
+ resource_dag_name = self._resource_name(details.id, RESOURCE_DAG_RUN)
416
443
  return self._is_authorized(method=method, resource_type=resource_dag_name, user=user)
417
444
 
418
445
  return False
@@ -444,7 +471,7 @@ class FabAuthManager(BaseAuthManager):
444
471
  raise AirflowException(f"Unknown DAG access entity: {dag_access_entity}")
445
472
  return _MAP_DAG_ACCESS_ENTITY_TO_FAB_RESOURCE_TYPE[dag_access_entity]
446
473
 
447
- def _resource_name_for_dag(self, dag_id: str) -> str:
474
+ def _resource_name(self, dag_id: str, resource_type: str) -> str:
448
475
  """
449
476
  Return the FAB resource name for a DAG id.
450
477
 
@@ -453,11 +480,9 @@ class FabAuthManager(BaseAuthManager):
453
480
  :meta private:
454
481
  """
455
482
  root_dag_id = self._get_root_dag_id(dag_id)
456
- if root_dag_id == RESOURCE_DAG:
457
- return root_dag_id
458
- if root_dag_id.startswith(RESOURCE_DAG_PREFIX):
459
- return root_dag_id
460
- return f"{RESOURCE_DAG_PREFIX}{root_dag_id}"
483
+ if hasattr(permissions, "resource_name"):
484
+ return getattr(permissions, "resource_name")(root_dag_id, resource_type)
485
+ return getattr(permissions, "resource_name_for_dag")(root_dag_id)
461
486
 
462
487
  @staticmethod
463
488
  def _get_user_permissions(user: BaseUser):
@@ -478,7 +503,7 @@ class FabAuthManager(BaseAuthManager):
478
503
 
479
504
  :meta private:
480
505
  """
481
- if "." in dag_id:
506
+ if "." in dag_id and hasattr(DagModel, "root_dag_id"):
482
507
  return self.appbuilder.get_session.scalar(
483
508
  select(DagModel.dag_id, DagModel.root_dag_id).where(DagModel.dag_id == dag_id).limit(1)
484
509
  )
@@ -344,7 +344,16 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
344
344
  ]
345
345
 
346
346
  # global resource for dag-level access
347
- DAG_ACTIONS = permissions.DAG_ACTIONS
347
+ RESOURCE_DETAILS_MAP = getattr(
348
+ permissions,
349
+ "RESOURCE_DETAILS_MAP",
350
+ {
351
+ permissions.RESOURCE_DAG: {
352
+ "actions": permissions.DAG_ACTIONS,
353
+ }
354
+ },
355
+ )
356
+ DAG_ACTIONS = RESOURCE_DETAILS_MAP[permissions.RESOURCE_DAG]["actions"]
348
357
 
349
358
  def __init__(self, appbuilder):
350
359
  # done in super, but we need it before we can call super.
@@ -1031,7 +1040,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1031
1040
  """Check if user has read or write access to some dags."""
1032
1041
  if dag_id and dag_id != "~":
1033
1042
  root_dag_id = self._get_root_dag_id(dag_id)
1034
- return self.has_access(action, permissions.resource_name_for_dag(root_dag_id))
1043
+ return self.has_access(action, self._resource_name(root_dag_id, permissions.RESOURCE_DAG))
1035
1044
 
1036
1045
  user = g.user
1037
1046
  if action == permissions.ACTION_CAN_READ:
@@ -1064,25 +1073,26 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1064
1073
  dags = dagbag.dags.values()
1065
1074
 
1066
1075
  for dag in dags:
1067
- root_dag_id = dag.parent_dag.dag_id if dag.parent_dag else dag.dag_id
1068
- dag_resource_name = permissions.resource_name_for_dag(root_dag_id)
1069
- for action_name in self.DAG_ACTIONS:
1070
- if (action_name, dag_resource_name) not in perms:
1071
- self._merge_perm(action_name, dag_resource_name)
1076
+ root_dag_id = (getattr(dag, "parent_dag", None) or dag).dag_id
1077
+ for resource_name, resource_values in self.RESOURCE_DETAILS_MAP.items():
1078
+ dag_resource_name = self._resource_name(root_dag_id, resource_name)
1079
+ for action_name in resource_values["actions"]:
1080
+ if (action_name, dag_resource_name) not in perms:
1081
+ self._merge_perm(action_name, dag_resource_name)
1072
1082
 
1073
1083
  if dag.access_control is not None:
1074
- self.sync_perm_for_dag(dag_resource_name, dag.access_control)
1084
+ self.sync_perm_for_dag(root_dag_id, dag.access_control)
1075
1085
 
1076
1086
  def prefixed_dag_id(self, dag_id: str) -> str:
1077
1087
  """Return the permission name for a DAG id."""
1078
1088
  warnings.warn(
1079
1089
  "`prefixed_dag_id` has been deprecated. "
1080
- "Please use `airflow.security.permissions.resource_name_for_dag` instead.",
1090
+ "Please use `airflow.security.permissions.resource_name` instead.",
1081
1091
  RemovedInAirflow3Warning,
1082
1092
  stacklevel=2,
1083
1093
  )
1084
1094
  root_dag_id = self._get_root_dag_id(dag_id)
1085
- return permissions.resource_name_for_dag(root_dag_id)
1095
+ return self._resource_name(root_dag_id, permissions.RESOURCE_DAG)
1086
1096
 
1087
1097
  def is_dag_resource(self, resource_name: str) -> bool:
1088
1098
  """Determine if a resource belongs to a DAG or all DAGs."""
@@ -1093,7 +1103,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1093
1103
  def sync_perm_for_dag(
1094
1104
  self,
1095
1105
  dag_id: str,
1096
- access_control: dict[str, Collection[str]] | None = None,
1106
+ access_control: dict[str, dict[str, Collection[str]]] | None = None,
1097
1107
  ) -> None:
1098
1108
  """
1099
1109
  Sync permissions for given dag id.
@@ -1101,62 +1111,78 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1101
1111
  The dag id surely exists in our dag bag as only / refresh button or DagBag will call this function.
1102
1112
 
1103
1113
  :param dag_id: the ID of the DAG whose permissions should be updated
1104
- :param access_control: a dict where each key is a role name and
1105
- each value is a set() of action names (e.g.,
1106
- {'can_read'}
1114
+ :param access_control: a dict where each key is a role name and each value can be:
1115
+ - a set() of DAGs resource action names (e.g. `{'can_read'}`)
1116
+ - or a dict where each key is a resource name ('DAGs' or 'DAG Runs') and each value
1117
+ is a set() of action names (e.g., `{'DAG Runs': {'can_create'}, 'DAGs': {'can_read'}}`)
1107
1118
  :return:
1108
1119
  """
1109
- dag_resource_name = permissions.resource_name_for_dag(dag_id)
1110
- for dag_action_name in self.DAG_ACTIONS:
1111
- self.create_permission(dag_action_name, dag_resource_name)
1120
+ for resource_name, resource_values in self.RESOURCE_DETAILS_MAP.items():
1121
+ dag_resource_name = self._resource_name(dag_id, resource_name)
1122
+ for dag_action_name in resource_values["actions"]:
1123
+ self.create_permission(dag_action_name, dag_resource_name)
1112
1124
 
1113
1125
  if access_control is not None:
1114
- self.log.debug("Syncing DAG-level permissions for DAG '%s'", dag_resource_name)
1115
- self._sync_dag_view_permissions(dag_resource_name, access_control)
1126
+ self.log.debug("Syncing DAG-level permissions for DAG '%s'", dag_id)
1127
+ self._sync_dag_view_permissions(dag_id, access_control.copy())
1116
1128
  else:
1117
1129
  self.log.debug(
1118
1130
  "Not syncing DAG-level permissions for DAG '%s' as access control is unset.",
1119
- dag_resource_name,
1131
+ dag_id,
1120
1132
  )
1121
1133
 
1122
- def _sync_dag_view_permissions(self, dag_id: str, access_control: dict[str, Collection[str]]) -> None:
1134
+ def _resource_name(self, dag_id: str, resource_name: str) -> str:
1135
+ """
1136
+ Get the resource name from permissions.
1137
+
1138
+ This method is to keep compatibility with new FAB versions
1139
+ running with old airflow versions.
1140
+ """
1141
+ if hasattr(permissions, "resource_name"):
1142
+ return getattr(permissions, "resource_name")(dag_id, resource_name)
1143
+ return getattr(permissions, "resource_name_for_dag")(dag_id)
1144
+
1145
+ def _sync_dag_view_permissions(
1146
+ self,
1147
+ dag_id: str,
1148
+ access_control: dict[str, dict[str, Collection[str]]],
1149
+ ) -> None:
1123
1150
  """
1124
1151
  Set the access policy on the given DAG's ViewModel.
1125
1152
 
1126
1153
  :param dag_id: the ID of the DAG whose permissions should be updated
1127
- :param access_control: a dict where each key is a role name and
1128
- each value is a set() of action names (e.g. {'can_read'})
1154
+ :param access_control: a dict where each key is a role name and each value is:
1155
+ - a dict where each key is a resource name ('DAGs' or 'DAG Runs') and each value
1156
+ is a set() of action names (e.g., `{'DAG Runs': {'can_create'}, 'DAGs': {'can_read'}}`)
1129
1157
  """
1130
- dag_resource_name = permissions.resource_name_for_dag(dag_id)
1131
1158
 
1132
- def _get_or_create_dag_permission(action_name: str) -> Permission | None:
1159
+ def _get_or_create_dag_permission(action_name: str, dag_resource_name: str) -> Permission | None:
1133
1160
  perm = self.get_permission(action_name, dag_resource_name)
1134
1161
  if not perm:
1135
1162
  self.log.info("Creating new action '%s' on resource '%s'", action_name, dag_resource_name)
1136
1163
  perm = self.create_permission(action_name, dag_resource_name)
1137
-
1138
1164
  return perm
1139
1165
 
1140
- def _revoke_stale_permissions(resource: Resource):
1141
- existing_dag_perms = self.get_resource_permissions(resource)
1142
- for perm in existing_dag_perms:
1143
- non_admin_roles = [role for role in perm.role if role.name != "Admin"]
1144
- for role in non_admin_roles:
1145
- target_perms_for_role = access_control.get(role.name, ())
1146
- if perm.action.name not in target_perms_for_role:
1147
- self.log.info(
1148
- "Revoking '%s' on DAG '%s' for role '%s'",
1149
- perm.action,
1150
- dag_resource_name,
1151
- role.name,
1152
- )
1153
- self.remove_permission_from_role(role, perm)
1154
-
1155
- resource = self.get_resource(dag_resource_name)
1156
- if resource:
1157
- _revoke_stale_permissions(resource)
1158
-
1159
- for rolename, action_names in access_control.items():
1166
+ # Revoking stale permissions for all possible DAG level resources
1167
+ for resource_name in self.RESOURCE_DETAILS_MAP.keys():
1168
+ dag_resource_name = self._resource_name(dag_id, resource_name)
1169
+ if resource := self.get_resource(dag_resource_name):
1170
+ existing_dag_perms = self.get_resource_permissions(resource)
1171
+ for perm in existing_dag_perms:
1172
+ non_admin_roles = [role for role in perm.role if role.name != "Admin"]
1173
+ for role in non_admin_roles:
1174
+ target_perms_for_role = access_control.get(role.name, {}).get(resource_name, set())
1175
+ if perm.action.name not in target_perms_for_role:
1176
+ self.log.info(
1177
+ "Revoking '%s' on DAG '%s' for role '%s'",
1178
+ perm.action,
1179
+ dag_resource_name,
1180
+ role.name,
1181
+ )
1182
+ self.remove_permission_from_role(role, perm)
1183
+
1184
+ # Adding the access control permissions
1185
+ for rolename, resource_actions in access_control.items():
1160
1186
  role = self.find_role(rolename)
1161
1187
  if not role:
1162
1188
  raise AirflowException(
@@ -1164,19 +1190,34 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1164
1190
  f"'{rolename}', but that role does not exist"
1165
1191
  )
1166
1192
 
1167
- action_names = set(action_names)
1168
- invalid_action_names = action_names - self.DAG_ACTIONS
1169
- if invalid_action_names:
1170
- raise AirflowException(
1171
- f"The access_control map for DAG '{dag_resource_name}' includes "
1172
- f"the following invalid permissions: {invalid_action_names}; "
1173
- f"The set of valid permissions is: {self.DAG_ACTIONS}"
1174
- )
1193
+ if isinstance(resource_actions, (set, list)):
1194
+ # Support for old-style access_control where only the actions are specified
1195
+ resource_actions = {permissions.RESOURCE_DAG: set(resource_actions)}
1196
+
1197
+ for resource_name, actions in resource_actions.items():
1198
+ if resource_name not in self.RESOURCE_DETAILS_MAP:
1199
+ raise AirflowException(
1200
+ f"The access_control map for DAG '{dag_id}' includes the following invalid "
1201
+ f"resource name: '{resource_name}'; "
1202
+ f"The set of valid resource names is: {self.RESOURCE_DETAILS_MAP.keys()}"
1203
+ )
1204
+
1205
+ dag_resource_name = self._resource_name(dag_id, resource_name)
1206
+ self.log.debug("Syncing DAG-level permissions for DAG '%s'", dag_resource_name)
1207
+
1208
+ invalid_actions = set(actions) - self.RESOURCE_DETAILS_MAP[resource_name]["actions"]
1209
+
1210
+ if invalid_actions:
1211
+ raise AirflowException(
1212
+ f"The access_control map for DAG '{dag_resource_name}' includes "
1213
+ f"the following invalid permissions: {invalid_actions}; "
1214
+ f"The set of valid permissions is: {self.RESOURCE_DETAILS_MAP[resource_name]['actions']}"
1215
+ )
1175
1216
 
1176
- for action_name in action_names:
1177
- dag_perm = _get_or_create_dag_permission(action_name)
1178
- if dag_perm:
1179
- self.add_permission_to_role(role, dag_perm)
1217
+ for action_name in actions:
1218
+ dag_perm = _get_or_create_dag_permission(action_name, dag_resource_name)
1219
+ if dag_perm:
1220
+ self.add_permission_to_role(role, dag_perm)
1180
1221
 
1181
1222
  def add_permissions_view(self, base_action_names, resource_name): # Keep name for compatibility with FAB.
1182
1223
  """
@@ -1307,8 +1348,9 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
1307
1348
  Add the missing ones to the table for admin.
1308
1349
  """
1309
1350
  session = self.appbuilder.get_session
1351
+ prefixes = getattr(permissions, "PREFIX_LIST", [permissions.RESOURCE_DAG_PREFIX])
1310
1352
  dag_resources = session.scalars(
1311
- select(Resource).where(Resource.name.like(f"{permissions.RESOURCE_DAG_PREFIX}%"))
1353
+ select(Resource).where(or_(*[Resource.name.like(f"{prefix}%") for prefix in prefixes]))
1312
1354
  )
1313
1355
  resource_ids = [resource.id for resource in dag_resources]
1314
1356
 
@@ -2786,7 +2828,7 @@ class FabAirflowSecurityManagerOverride(AirflowSecurityManagerV2):
2786
2828
  ).all()
2787
2829
 
2788
2830
  def _get_root_dag_id(self, dag_id: str) -> str:
2789
- if "." in dag_id:
2831
+ if "." in dag_id and hasattr(DagModel, "root_dag_id"):
2790
2832
  dm = self.appbuilder.get_session.execute(
2791
2833
  select(DagModel.dag_id, DagModel.root_dag_id).where(DagModel.dag_id == dag_id)
2792
2834
  ).one()
@@ -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": 1722149665,
31
+ "source-date-epoch": 1723970140,
32
32
  "versions": [
33
+ "1.3.0",
33
34
  "1.2.2",
34
35
  "1.2.1",
35
36
  "1.2.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apache-airflow-providers-fab
3
- Version: 1.2.2rc1
3
+ Version: 1.3.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>
@@ -21,15 +21,15 @@ Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Classifier: Topic :: System :: Monitoring
24
- Requires-Dist: apache-airflow>=2.9.0rc0
24
+ Requires-Dist: apache-airflow>=2.9.0
25
25
  Requires-Dist: flask-appbuilder==4.5.0
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
29
29
  Requires-Dist: jmespath>=0.7.0
30
30
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
31
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.2.2/changelog.html
32
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.2.2
31
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.3.0/changelog.html
32
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-fab/1.3.0
33
33
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
34
  Project-URL: Source Code, https://github.com/apache/airflow
35
35
  Project-URL: Twitter, https://twitter.com/ApacheAirflow
@@ -79,7 +79,7 @@ Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
79
79
 
80
80
  Package ``apache-airflow-providers-fab``
81
81
 
82
- Release: ``1.2.2.rc1``
82
+ Release: ``1.3.0``
83
83
 
84
84
 
85
85
  `Flask App Builder <https://flask-appbuilder.readthedocs.io/>`__
@@ -92,7 +92,7 @@ This is a provider package for ``fab`` provider. All classes for this provider p
92
92
  are in ``airflow.providers.fab`` python package.
93
93
 
94
94
  You can find package information and changelog for the provider
95
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.2.2/>`_.
95
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.3.0/>`_.
96
96
 
97
97
  Installation
98
98
  ------------
@@ -118,4 +118,4 @@ PIP package Version required
118
118
  ==================== ==================
119
119
 
120
120
  The changelog for the provider package can be found in the
121
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.2.2/changelog.html>`_.
121
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-fab/1.3.0/changelog.html>`_.
@@ -1,8 +1,8 @@
1
1
  airflow/providers/fab/LICENSE,sha256=FFb4jd2AXnOOf7XLP04pQW6jbdhG49TxlGY6fFpCV1Y,13609
2
- airflow/providers/fab/__init__.py,sha256=gpKs0MHwR5LA7BBox6bN37n2EetLwmzY5ij0hvm4VxM,1490
3
- airflow/providers/fab/get_provider_info.py,sha256=9hGTeDGYuq3eAFT4MNWtUc4EDDTE_-YCYXzS7vaJ5WM,3168
2
+ airflow/providers/fab/__init__.py,sha256=kO58YtLm_XBzc8nZAjDWfM7_KtjjflLtkHjHaLfhCZ4,1490
3
+ airflow/providers/fab/get_provider_info.py,sha256=ZaurwvXWOiDEyNg7_pCXctDAzEFYYEnPxA34Lf1emfQ,3189
4
4
  airflow/providers/fab/auth_manager/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
5
- airflow/providers/fab/auth_manager/fab_auth_manager.py,sha256=j_jAOd4iHPY5ZM6Uadi89zfYNndwlskPxBDSP14ieX4,19581
5
+ airflow/providers/fab/auth_manager/fab_auth_manager.py,sha256=lzUhvexJGkMHrNrTl7RMM-69KgrAvUEmkrvaNxDZnVQ,20830
6
6
  airflow/providers/fab/auth_manager/api/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
7
7
  airflow/providers/fab/auth_manager/api/auth/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
8
8
  airflow/providers/fab/auth_manager/api/auth/backend/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
@@ -25,14 +25,14 @@ airflow/providers/fab/auth_manager/openapi/__init__.py,sha256=9hdXHABrVpkbpjZgUf
25
25
  airflow/providers/fab/auth_manager/openapi/v1.yaml,sha256=xFlQMccLoGarx8SnQvGJ1DRfHo4jQ3p9DzoPqQINcCw,19380
26
26
  airflow/providers/fab/auth_manager/security_manager/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
27
27
  airflow/providers/fab/auth_manager/security_manager/constants.py,sha256=x1Sjl_Mu3wmaSy3NFZlHxK2z-juzWmMs1SrzJ0aiBBQ,907
28
- airflow/providers/fab/auth_manager/security_manager/override.py,sha256=1uklg2TcA-bYwgFFcVIIrrc_ANfvBCpaM_84gEFcvws,112686
28
+ airflow/providers/fab/auth_manager/security_manager/override.py,sha256=TiZGNdAwpGe3GlcOEG2P0AI_EwBQFs1Hwtant0pKTVI,115241
29
29
  airflow/providers/fab/auth_manager/views/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
30
30
  airflow/providers/fab/auth_manager/views/permissions.py,sha256=k5APUTqqKZqMxCWlKrUEgqdDVrGa9719HJ3UmFpiSLc,2886
31
31
  airflow/providers/fab/auth_manager/views/roles_list.py,sha256=o_VqnLbQa4sisKxLwyx6VCl3HmvjKcjkrJG23R81FMQ,1494
32
32
  airflow/providers/fab/auth_manager/views/user.py,sha256=KaBWeBMy5j8o9qwe0RDHhtToO4aC6pH_m7N9IcIj1xM,5995
33
33
  airflow/providers/fab/auth_manager/views/user_edit.py,sha256=d8wQ_8Rk8Ce95sCElZIXN7ATwbXrT2Tauqn5uTwuo2E,2140
34
34
  airflow/providers/fab/auth_manager/views/user_stats.py,sha256=zP2eX6e40rpEohJcvnvri4Khu3Q4ULLxjz1zOWvOr8A,1300
35
- apache_airflow_providers_fab-1.2.2rc1.dist-info/entry_points.txt,sha256=m05kASp7vFi0ZmQ--CFp7GeJpPL7UT2RQF8EEP5XRX8,99
36
- apache_airflow_providers_fab-1.2.2rc1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
37
- apache_airflow_providers_fab-1.2.2rc1.dist-info/METADATA,sha256=FjUcELkKXgdkkKe5PK9j9lNPodZkBamrLD7NZ-SFZB4,5022
38
- apache_airflow_providers_fab-1.2.2rc1.dist-info/RECORD,,
35
+ apache_airflow_providers_fab-1.3.0.dist-info/entry_points.txt,sha256=m05kASp7vFi0ZmQ--CFp7GeJpPL7UT2RQF8EEP5XRX8,99
36
+ apache_airflow_providers_fab-1.3.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
37
+ apache_airflow_providers_fab-1.3.0.dist-info/METADATA,sha256=dnZF6-n5lZ054WHgGNObusWJiqjaiJYv1NuhZY7G_Hc,5012
38
+ apache_airflow_providers_fab-1.3.0.dist-info/RECORD,,