From 652ffec36aa612e0a442e56d5e71711b617b13f9 Mon Sep 17 00:00:00 2001 From: Jed Cunningham Date: Tue, 25 Feb 2025 20:38:18 -0700 Subject: [PATCH 01/19] Fix breeze api-server - missed it during config move When I renamed the command to start the fastapi api server, I missed updating the breeze config to reflect the new config section. --- dev/breeze/doc/03_developer_tasks.rst | 2 +- dev/breeze/src/airflow_breeze/global_constants.py | 2 +- dev/breeze/src/airflow_breeze/params/shell_params.py | 6 +++--- dev/breeze/src/airflow_breeze/utils/visuals.py | 6 +++--- scripts/ci/docker-compose/base-ports.yml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/breeze/doc/03_developer_tasks.rst b/dev/breeze/doc/03_developer_tasks.rst index 51c07e62a9c48..d41655d1229a8 100644 --- a/dev/breeze/doc/03_developer_tasks.rst +++ b/dev/breeze/doc/03_developer_tasks.rst @@ -156,7 +156,7 @@ You can change the used host port numbers by setting appropriate environment var * ``SSH_PORT`` * ``WEBSERVER_HOST_PORT`` -* ``FASTAPI_API_HOST_PORT`` +* ``API_SERVER_HOST_PORT`` * ``POSTGRES_HOST_PORT`` * ``MYSQL_HOST_PORT`` * ``MSSQL_HOST_PORT`` diff --git a/dev/breeze/src/airflow_breeze/global_constants.py b/dev/breeze/src/airflow_breeze/global_constants.py index f31d9d675eba8..e9997ac6aca88 100644 --- a/dev/breeze/src/airflow_breeze/global_constants.py +++ b/dev/breeze/src/airflow_breeze/global_constants.py @@ -336,7 +336,7 @@ def get_default_platform_machine() -> str: SSH_PORT = "12322" WEBSERVER_HOST_PORT = "28080" VITE_DEV_PORT = "5173" -FASTAPI_API_HOST_PORT = "29091" +API_SERVER_HOST_PORT = "29091" CELERY_BROKER_URLS_MAP = {"rabbitmq": "amqp://guest:guest@rabbitmq:5672", "redis": "redis://redis:6379/0"} SQLITE_URL = "sqlite:////root/airflow/sqlite/airflow.db" diff --git a/dev/breeze/src/airflow_breeze/params/shell_params.py b/dev/breeze/src/airflow_breeze/params/shell_params.py index 292c3c19ba227..01d14a9f0a481 100644 --- a/dev/breeze/src/airflow_breeze/params/shell_params.py +++ b/dev/breeze/src/airflow_breeze/params/shell_params.py @@ -35,6 +35,7 @@ ALLOWED_POSTGRES_VERSIONS, ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS, APACHE_AIRFLOW_GITHUB_REPOSITORY, + API_SERVER_HOST_PORT, CELERY_BROKER_URLS_MAP, CELERY_EXECUTOR, DEFAULT_CELERY_BROKER, @@ -42,7 +43,6 @@ DOCKER_DEFAULT_PLATFORM, DRILL_HOST_PORT, EDGE_EXECUTOR, - FASTAPI_API_HOST_PORT, FLOWER_HOST_PORT, KEYCLOAK_INTEGRATION, MOUNT_ALL, @@ -507,7 +507,7 @@ def env_variables_for_docker_commands(self) -> dict[str, str]: _set_var(_env, "AIRFLOW_VERSION", self.airflow_version) _set_var(_env, "AIRFLOW__CELERY__BROKER_URL", self.airflow_celery_broker_url) _set_var(_env, "AIRFLOW__CORE__EXECUTOR", self.executor) - _set_var(_env, "AIRFLOW__FASTAPI__BASE_URL", f"http://localhost:{FASTAPI_API_HOST_PORT}") + _set_var(_env, "AIRFLOW__API__BASE_URL", f"http://localhost:{API_SERVER_HOST_PORT}") if self.executor == EDGE_EXECUTOR: _set_var( _env, "AIRFLOW__CORE__EXECUTOR", "airflow.providers.edge.executors.edge_executor.EdgeExecutor" @@ -618,7 +618,7 @@ def env_variables_for_docker_commands(self) -> dict[str, str]: _set_var(_env, "VERBOSE_COMMANDS", self.verbose_commands) _set_var(_env, "VERSION_SUFFIX_FOR_PYPI", self.version_suffix_for_pypi) _set_var(_env, "WEBSERVER_HOST_PORT", None, WEBSERVER_HOST_PORT) - _set_var(_env, "FASTAPI_API_HOST_PORT", None, FASTAPI_API_HOST_PORT) + _set_var(_env, "API_SERVER_HOST_PORT", None, API_SERVER_HOST_PORT) _set_var(_env, "_AIRFLOW_RUN_DB_TESTS_ONLY", self.run_db_tests_only) _set_var(_env, "_AIRFLOW_SKIP_DB_TESTS", self.skip_db_tests) self._generate_env_for_docker_compose_file_if_needed(_env) diff --git a/dev/breeze/src/airflow_breeze/utils/visuals.py b/dev/breeze/src/airflow_breeze/utils/visuals.py index 94258ac4005ce..090da53138934 100644 --- a/dev/breeze/src/airflow_breeze/utils/visuals.py +++ b/dev/breeze/src/airflow_breeze/utils/visuals.py @@ -21,7 +21,7 @@ from __future__ import annotations from airflow_breeze.global_constants import ( - FASTAPI_API_HOST_PORT, + API_SERVER_HOST_PORT, FLOWER_HOST_PORT, MYSQL_HOST_PORT, POSTGRES_HOST_PORT, @@ -83,7 +83,7 @@ Ports are forwarded to the running docker containers for webserver and database * {SSH_PORT} -> forwarded to Airflow ssh server -> airflow:22 * {WEBSERVER_HOST_PORT} -> forwarded to Airflow webserver -> airflow:8080 - * {FASTAPI_API_HOST_PORT} -> forwarded to Airflow FastAPI API -> airflow:9091 + * {API_SERVER_HOST_PORT} -> forwarded to Airflow api server API -> airflow:9091 * {FLOWER_HOST_PORT} -> forwarded to Flower dashboard -> airflow:5555 * {POSTGRES_HOST_PORT} -> forwarded to Postgres database -> postgres:5432 * {MYSQL_HOST_PORT} -> forwarded to MySQL database -> mysql:3306 @@ -93,7 +93,7 @@ * ssh connection for remote debugging: ssh -p {SSH_PORT} airflow@127.0.0.1 (password: airflow) * Webserver: http://127.0.0.1:{WEBSERVER_HOST_PORT} - * FastAPI API: http://127.0.0.1:{FASTAPI_API_HOST_PORT} + * API server: http://127.0.0.1:{API_SERVER_HOST_PORT} * Flower: http://127.0.0.1:{FLOWER_HOST_PORT} * Postgres: jdbc:postgresql://127.0.0.1:{POSTGRES_HOST_PORT}/airflow?user=postgres&password=airflow * Mysql: jdbc:mysql://127.0.0.1:{MYSQL_HOST_PORT}/airflow?user=root diff --git a/scripts/ci/docker-compose/base-ports.yml b/scripts/ci/docker-compose/base-ports.yml index 17a935cd27e1c..8f8a9bf2bb9ea 100644 --- a/scripts/ci/docker-compose/base-ports.yml +++ b/scripts/ci/docker-compose/base-ports.yml @@ -20,5 +20,5 @@ services: ports: - "${SSH_PORT}:22" - "${WEBSERVER_HOST_PORT}:8080" - - "${FASTAPI_API_HOST_PORT}:9091" + - "${API_SERVER_HOST_PORT}:9091" - "${FLOWER_HOST_PORT}:5555" From 44e98837904b183eb05646151b4b147d02103659 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Thu, 27 Feb 2025 12:51:50 +0530 Subject: [PATCH 02/19] init asset --- .../core_api/openapi/v1-generated.yaml | 17 +++++++++++++++++ .../core_api/routes/public/assets.py | 2 ++ airflow/api_fastapi/core_api/security.py | 19 ++++++++++++++++++- airflow/ui/openapi-gen/queries/common.ts | 4 +++- airflow/ui/openapi-gen/queries/prefetch.ts | 6 +++++- airflow/ui/openapi-gen/queries/queries.ts | 7 +++++-- airflow/ui/openapi-gen/queries/suspense.ts | 7 +++++-- .../ui/openapi-gen/requests/services.gen.ts | 2 ++ airflow/ui/openapi-gen/requests/types.gen.ts | 1 + tests/api_fastapi/conftest.py | 19 +++++++++++++++++++ .../core_api/routes/public/test_assets.py | 4 ++++ 11 files changed, 81 insertions(+), 7 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index a71113cb13bd4..1902f3fd3a6ea 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -528,7 +528,17 @@ paths: summary: Get Assets description: Get assets. operationId: get_assets + security: + - OAuth2PasswordBearer: [] parameters: + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri - name: limit in: query required: false @@ -11286,3 +11296,10 @@ components: - value title: XComUpdateBody description: Payload serializer for updating an XCom entry. + securitySchemes: + OAuth2PasswordBearer: + type: oauth2 + flows: + password: + scopes: {} + tokenUrl: token diff --git a/airflow/api_fastapi/core_api/routes/public/assets.py b/airflow/api_fastapi/core_api/routes/public/assets.py index 46cb9bf2c7b00..3a01c2c121c81 100644 --- a/airflow/api_fastapi/core_api/routes/public/assets.py +++ b/airflow/api_fastapi/core_api/routes/public/assets.py @@ -53,6 +53,7 @@ ) from airflow.api_fastapi.core_api.datamodels.dag_run import DAGRunResponse from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc +from airflow.api_fastapi.core_api.security import requires_access_asset from airflow.api_fastapi.logging.decorators import action_logging from airflow.assets.manager import asset_manager from airflow.models.asset import ( @@ -91,6 +92,7 @@ def _generate_queued_event_where_clause( @assets_router.get( "/assets", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_assets( limit: QueryLimit, diff --git a/airflow/api_fastapi/core_api/security.py b/airflow/api_fastapi/core_api/security.py index eac282e7e3cab..45c6730a130ec 100644 --- a/airflow/api_fastapi/core_api/security.py +++ b/airflow/api_fastapi/core_api/security.py @@ -25,7 +25,7 @@ from airflow.api_fastapi.app import get_auth_manager from airflow.auth.managers.models.base_user import BaseUser -from airflow.auth.managers.models.resource_details import DagAccessEntity, DagDetails +from airflow.auth.managers.models.resource_details import AssetDetails, DagAccessEntity, DagDetails from airflow.configuration import conf from airflow.utils.jwt_signer import JWTSigner, get_signing_key @@ -82,6 +82,23 @@ def callback(): return inner +def requires_access_asset(method: ResourceMethod) -> Callable: + def inner( + uri: str | None = None, + user: Annotated[BaseUser | None, Depends(get_user)] = None, + ) -> None: + def callback(): + return get_auth_manager().is_authorized_dag( + method=method, details=AssetDetails(uri=uri), user=user + ) + + _requires_access( + is_authorized_callback=callback, + ) + + return inner + + def _requires_access( *, is_authorized_callback: Callable[[], bool], diff --git a/airflow/ui/openapi-gen/queries/common.ts b/airflow/ui/openapi-gen/queries/common.ts index 151e3b100a9cf..c2aa8f8cedffc 100644 --- a/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow/ui/openapi-gen/queries/common.ts @@ -63,6 +63,7 @@ export const UseAssetServiceGetAssetsKeyFn = ( namePattern, offset, orderBy, + uri, uriPattern, }: { dagIds?: string[]; @@ -70,12 +71,13 @@ export const UseAssetServiceGetAssetsKeyFn = ( namePattern?: string; offset?: number; orderBy?: string; + uri?: string; uriPattern?: string; } = {}, queryKey?: Array, ) => [ useAssetServiceGetAssetsKey, - ...(queryKey ?? [{ dagIds, limit, namePattern, offset, orderBy, uriPattern }]), + ...(queryKey ?? [{ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }]), ]; export type AssetServiceGetAssetAliasesDefaultResponse = Awaited< ReturnType diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow/ui/openapi-gen/queries/prefetch.ts index c833e4268706b..6a11969fab89a 100644 --- a/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow/ui/openapi-gen/queries/prefetch.ts @@ -59,6 +59,7 @@ export const prefetchUseAssetServiceNextRunAssets = ( * Get Assets * Get assets. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -76,6 +77,7 @@ export const prefetchUseAssetServiceGetAssets = ( namePattern, offset, orderBy, + uri, uriPattern, }: { dagIds?: string[]; @@ -83,6 +85,7 @@ export const prefetchUseAssetServiceGetAssets = ( namePattern?: string; offset?: number; orderBy?: string; + uri?: string; uriPattern?: string; } = {}, ) => @@ -93,9 +96,10 @@ export const prefetchUseAssetServiceGetAssets = ( namePattern, offset, orderBy, + uri, uriPattern, }), - queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uriPattern }), + queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }), }); /** * Get Asset Aliases diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index 2fdd58c4ec273..9e3d3a5cae654 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -88,6 +88,7 @@ export const useAssetServiceNextRunAssets = < * Get Assets * Get assets. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -108,6 +109,7 @@ export const useAssetServiceGetAssets = < namePattern, offset, orderBy, + uri, uriPattern, }: { dagIds?: string[]; @@ -115,6 +117,7 @@ export const useAssetServiceGetAssets = < namePattern?: string; offset?: number; orderBy?: string; + uri?: string; uriPattern?: string; } = {}, queryKey?: TQueryKey, @@ -122,11 +125,11 @@ export const useAssetServiceGetAssets = < ) => useQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn( - { dagIds, limit, namePattern, offset, orderBy, uriPattern }, + { dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }, queryKey, ), queryFn: () => - AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uriPattern }) as TData, + AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/queries/suspense.ts b/airflow/ui/openapi-gen/queries/suspense.ts index 48b17556fd9ec..6c89053408a69 100644 --- a/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow/ui/openapi-gen/queries/suspense.ts @@ -65,6 +65,7 @@ export const useAssetServiceNextRunAssetsSuspense = < * Get Assets * Get assets. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -85,6 +86,7 @@ export const useAssetServiceGetAssetsSuspense = < namePattern, offset, orderBy, + uri, uriPattern, }: { dagIds?: string[]; @@ -92,6 +94,7 @@ export const useAssetServiceGetAssetsSuspense = < namePattern?: string; offset?: number; orderBy?: string; + uri?: string; uriPattern?: string; } = {}, queryKey?: TQueryKey, @@ -99,11 +102,11 @@ export const useAssetServiceGetAssetsSuspense = < ) => useSuspenseQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn( - { dagIds, limit, namePattern, offset, orderBy, uriPattern }, + { dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }, queryKey, ), queryFn: () => - AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uriPattern }) as TData, + AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index 81b649d31cb97..db3eeefa3b668 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -236,6 +236,7 @@ export class AssetService { * Get Assets * Get assets. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -250,6 +251,7 @@ export class AssetService { method: "GET", url: "/public/assets", query: { + uri: data.uri, limit: data.limit, offset: data.offset, name_pattern: data.namePattern, diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index 32982e08b0195..0924a7922bc48 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1612,6 +1612,7 @@ export type GetAssetsData = { namePattern?: string | null; offset?: number; orderBy?: string; + uri?: string | null; uriPattern?: string | null; }; diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index 3e5b44651f0dd..fd5df6efa7ec1 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -23,6 +23,8 @@ from fastapi.testclient import TestClient from airflow.api_fastapi.app import create_app +from airflow.auth.managers.simple.simple_auth_manager import SimpleAuthManager +from airflow.auth.managers.simple.user import SimpleAuthManagerUser from airflow.models import Connection from airflow.models.dag_version import DagVersion from airflow.models.serialized_dag import SerializedDagModel @@ -34,6 +36,23 @@ @pytest.fixture def test_client(): + with conf_vars( + { + ( + "core", + "auth_manager", + ): "airflow.auth.managers.simple.simple_auth_manager.SimpleAuthManager", + } + ): + auth_manager = SimpleAuthManager() + token = auth_manager._get_token_signer().generate_signed_token( + auth_manager.serialize_user(SimpleAuthManagerUser(username="test", role="admin")) + ) + yield TestClient(create_app(), headers={"Authorization": f"Bearer {token}"}) + + +@pytest.fixture +def unauthenticated_test_client(): return TestClient(create_app()) diff --git a/tests/api_fastapi/core_api/routes/public/test_assets.py b/tests/api_fastapi/core_api/routes/public/test_assets.py index 764d16b5e8326..7190e3b86eb6b 100644 --- a/tests/api_fastapi/core_api/routes/public/test_assets.py +++ b/tests/api_fastapi/core_api/routes/public/test_assets.py @@ -263,6 +263,10 @@ def test_should_respond_200(self, test_client, session): "total_entries": 2, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets") + assert response.status_code == 401 + def test_order_by_raises_400_for_invalid_attr(self, test_client, session): response = test_client.get("/public/assets?order_by=fake") From 9ab906698a7137e4166fd074cae8a5abacf2733b Mon Sep 17 00:00:00 2001 From: kalyanr Date: Thu, 27 Feb 2025 15:01:30 +0530 Subject: [PATCH 03/19] update rest --- .../core_api/openapi/v1-generated.yaml | 129 +++++++++++++++++- .../core_api/routes/public/assets.py | 19 ++- airflow/ui/openapi-gen/queries/common.ts | 27 +++- airflow/ui/openapi-gen/queries/prefetch.ts | 47 +++++-- airflow/ui/openapi-gen/queries/queries.ts | 84 +++++++++--- airflow/ui/openapi-gen/queries/suspense.ts | 50 +++++-- .../ui/openapi-gen/requests/services.gen.ts | 32 +++++ airflow/ui/openapi-gen/requests/types.gen.ts | 16 ++- .../core_api/routes/public/test_assets.py | 46 +++++++ 9 files changed, 389 insertions(+), 61 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index 1902f3fd3a6ea..fd5e400a87a7d 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -624,7 +624,17 @@ paths: summary: Get Asset Aliases description: Get asset aliases. operationId: get_asset_aliases + security: + - OAuth2PasswordBearer: [] parameters: + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri - name: limit in: query required: false @@ -694,6 +704,8 @@ paths: summary: Get Asset Alias description: Get an asset alias. operationId: get_asset_alias + security: + - OAuth2PasswordBearer: [] parameters: - name: asset_alias_id in: path @@ -701,6 +713,14 @@ paths: schema: type: integer title: Asset Alias Id + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -738,7 +758,17 @@ paths: summary: Get Asset Events description: Get asset events. operationId: get_asset_events + security: + - OAuth2PasswordBearer: [] parameters: + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri - name: limit in: query required: false @@ -857,6 +887,17 @@ paths: summary: Create Asset Event description: Create asset events. operationId: create_asset_event + security: + - OAuth2PasswordBearer: [] + parameters: + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri requestBody: required: true content: @@ -901,6 +942,8 @@ paths: summary: Materialize Asset description: Materialize an asset by triggering a DAG run that produces it. operationId: materialize_asset + security: + - OAuth2PasswordBearer: [] parameters: - name: asset_id in: path @@ -908,6 +951,14 @@ paths: schema: type: integer title: Asset Id + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -952,6 +1003,8 @@ paths: summary: Get Asset Queued Events description: Get queued asset events for an asset. operationId: get_asset_queued_events + security: + - OAuth2PasswordBearer: [] parameters: - name: asset_id in: path @@ -967,6 +1020,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -1004,6 +1065,8 @@ paths: summary: Delete Asset Queued Events description: Delete queued asset events for an asset. operationId: delete_asset_queued_events + security: + - OAuth2PasswordBearer: [] parameters: - name: asset_id in: path @@ -1019,6 +1082,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '204': description: Successful Response @@ -1053,6 +1124,8 @@ paths: summary: Get Asset description: Get an asset. operationId: get_asset + security: + - OAuth2PasswordBearer: [] parameters: - name: asset_id in: path @@ -1060,6 +1133,14 @@ paths: schema: type: integer title: Asset Id + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -1098,12 +1179,16 @@ paths: summary: Get Dag Asset Queued Events description: Get queued asset events for a DAG. operationId: get_dag_asset_queued_events + security: + - OAuth2PasswordBearer: [] parameters: - name: dag_id in: path required: true schema: - type: string + anyOf: + - type: string + - type: 'null' title: Dag Id - name: before in: query @@ -1113,6 +1198,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -1149,6 +1242,8 @@ paths: - Asset summary: Delete Dag Asset Queued Events operationId: delete_dag_asset_queued_events + security: + - OAuth2PasswordBearer: [] parameters: - name: dag_id in: path @@ -1164,6 +1259,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '204': description: Successful Response @@ -1204,12 +1307,16 @@ paths: summary: Get Dag Asset Queued Event description: Get a queued asset event for a DAG. operationId: get_dag_asset_queued_event + security: + - OAuth2PasswordBearer: [] parameters: - name: dag_id in: path required: true schema: - type: string + anyOf: + - type: string + - type: 'null' title: Dag Id - name: asset_id in: path @@ -1225,6 +1332,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response @@ -1262,6 +1377,8 @@ paths: summary: Delete Dag Asset Queued Event description: Delete a queued asset event for a DAG. operationId: delete_dag_asset_queued_event + security: + - OAuth2PasswordBearer: [] parameters: - name: dag_id in: path @@ -1283,6 +1400,14 @@ paths: - type: string - type: 'null' title: Before + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '204': description: Successful Response diff --git a/airflow/api_fastapi/core_api/routes/public/assets.py b/airflow/api_fastapi/core_api/routes/public/assets.py index 3a01c2c121c81..382f049b04db8 100644 --- a/airflow/api_fastapi/core_api/routes/public/assets.py +++ b/airflow/api_fastapi/core_api/routes/public/assets.py @@ -53,7 +53,7 @@ ) from airflow.api_fastapi.core_api.datamodels.dag_run import DAGRunResponse from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc -from airflow.api_fastapi.core_api.security import requires_access_asset +from airflow.api_fastapi.core_api.security import requires_access_asset, requires_access_dag from airflow.api_fastapi.logging.decorators import action_logging from airflow.assets.manager import asset_manager from airflow.models.asset import ( @@ -130,6 +130,7 @@ def get_assets( @assets_router.get( "/assets/aliases", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_aliases( limit: QueryLimit, @@ -160,6 +161,7 @@ def get_asset_aliases( @assets_router.get( "/assets/aliases/{asset_alias_id}", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_alias(asset_alias_id: int, session: SessionDep): """Get an asset alias.""" @@ -175,6 +177,7 @@ def get_asset_alias(asset_alias_id: int, session: SessionDep): @assets_router.get( "/assets/events", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_events( limit: QueryLimit, @@ -234,7 +237,7 @@ def get_asset_events( @assets_router.post( "/assets/events", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), - dependencies=[Depends(action_logging())], + dependencies=[Depends(requires_access_asset(method="POST")), Depends(action_logging())], ) def create_asset_event( body: CreateAssetEventsBody, @@ -261,7 +264,7 @@ def create_asset_event( @assets_router.post( "/assets/{asset_id}/materialize", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND, status.HTTP_409_CONFLICT]), - dependencies=[Depends(action_logging())], + dependencies=[Depends(requires_access_asset(method="POST")), Depends(action_logging())], ) def materialize_asset( asset_id: int, @@ -308,6 +311,7 @@ def materialize_asset( @assets_router.get( "/assets/{asset_id}/queuedEvents", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_queued_events( asset_id: int, @@ -341,6 +345,7 @@ def get_asset_queued_events( @assets_router.get( "/assets/{asset_id}", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset( asset_id: int, @@ -362,6 +367,7 @@ def get_asset( @assets_router.get( "/dags/{dag_id}/assets/queuedEvents", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET")), Depends(requires_access_dag(method="GET"))], ) def get_dag_asset_queued_events( dag_id: str, @@ -391,6 +397,7 @@ def get_dag_asset_queued_events( @assets_router.get( "/dags/{dag_id}/assets/{asset_id}/queuedEvents", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), + dependencies=[Depends(requires_access_asset(method="GET")), Depends(requires_access_dag(method="GET"))], ) def get_dag_asset_queued_event( dag_id: str, @@ -415,7 +422,7 @@ def get_dag_asset_queued_event( "/assets/{asset_id}/queuedEvents", status_code=status.HTTP_204_NO_CONTENT, responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), - dependencies=[Depends(action_logging())], + dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], ) def delete_asset_queued_events( asset_id: int, @@ -442,7 +449,7 @@ def delete_asset_queued_events( status.HTTP_404_NOT_FOUND, ] ), - dependencies=[Depends(action_logging())], + dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], ) def delete_dag_asset_queued_events( dag_id: str, @@ -467,7 +474,7 @@ def delete_dag_asset_queued_events( status.HTTP_404_NOT_FOUND, ] ), - dependencies=[Depends(action_logging())], + dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], ) def delete_dag_asset_queued_event( dag_id: str, diff --git a/airflow/ui/openapi-gen/queries/common.ts b/airflow/ui/openapi-gen/queries/common.ts index c2aa8f8cedffc..8ee7ccd27049a 100644 --- a/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow/ui/openapi-gen/queries/common.ts @@ -93,14 +93,16 @@ export const UseAssetServiceGetAssetAliasesKeyFn = ( namePattern, offset, orderBy, + uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; + uri?: string; } = {}, queryKey?: Array, -) => [useAssetServiceGetAssetAliasesKey, ...(queryKey ?? [{ limit, namePattern, offset, orderBy }])]; +) => [useAssetServiceGetAssetAliasesKey, ...(queryKey ?? [{ limit, namePattern, offset, orderBy, uri }])]; export type AssetServiceGetAssetAliasDefaultResponse = Awaited>; export type AssetServiceGetAssetAliasQueryResult< TData = AssetServiceGetAssetAliasDefaultResponse, @@ -110,11 +112,13 @@ export const useAssetServiceGetAssetAliasKey = "AssetServiceGetAssetAlias"; export const UseAssetServiceGetAssetAliasKeyFn = ( { assetAliasId, + uri, }: { assetAliasId: number; + uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetAliasKey, ...(queryKey ?? [{ assetAliasId }])]; +) => [useAssetServiceGetAssetAliasKey, ...(queryKey ?? [{ assetAliasId, uri }])]; export type AssetServiceGetAssetEventsDefaultResponse = Awaited< ReturnType >; @@ -135,6 +139,7 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId, timestampGte, timestampLte, + uri, }: { assetId?: number; limit?: number; @@ -146,6 +151,7 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId?: string; timestampGte?: string; timestampLte?: string; + uri?: string; } = {}, queryKey?: Array, ) => [ @@ -162,6 +168,7 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId, timestampGte, timestampLte, + uri, }, ]), ]; @@ -177,12 +184,14 @@ export const UseAssetServiceGetAssetQueuedEventsKeyFn = ( { assetId, before, + uri, }: { assetId: number; before?: string; + uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetQueuedEventsKey, ...(queryKey ?? [{ assetId, before }])]; +) => [useAssetServiceGetAssetQueuedEventsKey, ...(queryKey ?? [{ assetId, before, uri }])]; export type AssetServiceGetAssetDefaultResponse = Awaited>; export type AssetServiceGetAssetQueryResult< TData = AssetServiceGetAssetDefaultResponse, @@ -192,11 +201,13 @@ export const useAssetServiceGetAssetKey = "AssetServiceGetAsset"; export const UseAssetServiceGetAssetKeyFn = ( { assetId, + uri, }: { assetId: number; + uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetKey, ...(queryKey ?? [{ assetId }])]; +) => [useAssetServiceGetAssetKey, ...(queryKey ?? [{ assetId, uri }])]; export type AssetServiceGetDagAssetQueuedEventsDefaultResponse = Awaited< ReturnType >; @@ -209,12 +220,14 @@ export const UseAssetServiceGetDagAssetQueuedEventsKeyFn = ( { before, dagId, + uri, }: { before?: string; dagId: string; + uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetDagAssetQueuedEventsKey, ...(queryKey ?? [{ before, dagId }])]; +) => [useAssetServiceGetDagAssetQueuedEventsKey, ...(queryKey ?? [{ before, dagId, uri }])]; export type AssetServiceGetDagAssetQueuedEventDefaultResponse = Awaited< ReturnType >; @@ -228,13 +241,15 @@ export const UseAssetServiceGetDagAssetQueuedEventKeyFn = ( assetId, before, dagId, + uri, }: { assetId: number; before?: string; dagId: string; + uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetDagAssetQueuedEventKey, ...(queryKey ?? [{ assetId, before, dagId }])]; +) => [useAssetServiceGetDagAssetQueuedEventKey, ...(queryKey ?? [{ assetId, before, dagId, uri }])]; export type ConfigServiceGetConfigsDefaultResponse = Awaited>; export type ConfigServiceGetConfigsQueryResult< TData = ConfigServiceGetConfigsDefaultResponse, diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow/ui/openapi-gen/queries/prefetch.ts index 6a11969fab89a..564565dd14f23 100644 --- a/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow/ui/openapi-gen/queries/prefetch.ts @@ -105,6 +105,7 @@ export const prefetchUseAssetServiceGetAssets = ( * Get Asset Aliases * Get asset aliases. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -119,22 +120,25 @@ export const prefetchUseAssetServiceGetAssetAliases = ( namePattern, offset, orderBy, + uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; + uri?: string; } = {}, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }), + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy, uri }), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }), }); /** * Get Asset Alias * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId + * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -142,18 +146,21 @@ export const prefetchUseAssetServiceGetAssetAlias = ( queryClient: QueryClient, { assetAliasId, + uri, }: { assetAliasId: number; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }), - queryFn: () => AssetService.getAssetAlias({ assetAliasId }), + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }), + queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }), }); /** * Get Asset Events * Get asset events. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.orderBy @@ -180,6 +187,7 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, + uri, }: { assetId?: number; limit?: number; @@ -191,6 +199,7 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId?: string; timestampGte?: string; timestampLte?: string; + uri?: string; } = {}, ) => queryClient.prefetchQuery({ @@ -205,6 +214,7 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, + uri, }), queryFn: () => AssetService.getAssetEvents({ @@ -218,6 +228,7 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, + uri, }), }); /** @@ -226,6 +237,7 @@ export const prefetchUseAssetServiceGetAssetEvents = ( * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -234,20 +246,23 @@ export const prefetchUseAssetServiceGetAssetQueuedEvents = ( { assetId, before, + uri, }: { assetId: number; before?: string; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }), + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }), }); /** * Get Asset * Get an asset. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -255,13 +270,15 @@ export const prefetchUseAssetServiceGetAsset = ( queryClient: QueryClient, { assetId, + uri, }: { assetId: number; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }), - queryFn: () => AssetService.getAsset({ assetId }), + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }), + queryFn: () => AssetService.getAsset({ assetId, uri }), }); /** * Get Dag Asset Queued Events @@ -269,6 +286,7 @@ export const prefetchUseAssetServiceGetAsset = ( * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -277,14 +295,16 @@ export const prefetchUseAssetServiceGetDagAssetQueuedEvents = ( { before, dagId, + uri, }: { before?: string; dagId: string; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId }), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId }), + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }), + queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }), }); /** * Get Dag Asset Queued Event @@ -293,6 +313,7 @@ export const prefetchUseAssetServiceGetDagAssetQueuedEvents = ( * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -302,15 +323,17 @@ export const prefetchUseAssetServiceGetDagAssetQueuedEvent = ( assetId, before, dagId, + uri, }: { assetId: number; before?: string; dagId: string; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }), + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }), }); /** * Get Configs diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index 9e3d3a5cae654..cef95a984695e 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -136,6 +136,7 @@ export const useAssetServiceGetAssets = < * Get Asset Aliases * Get asset aliases. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -153,18 +154,23 @@ export const useAssetServiceGetAssetAliases = < namePattern, offset, orderBy, + uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; + uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn( + { limit, namePattern, offset, orderBy, uri }, + queryKey, + ), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }) as TData, ...options, }); /** @@ -172,6 +178,7 @@ export const useAssetServiceGetAssetAliases = < * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId + * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -182,21 +189,24 @@ export const useAssetServiceGetAssetAlias = < >( { assetAliasId, + uri, }: { assetAliasId: number; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }, queryKey), - queryFn: () => AssetService.getAssetAlias({ assetAliasId }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }, queryKey), + queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }) as TData, ...options, }); /** * Get Asset Events * Get asset events. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.orderBy @@ -226,6 +236,7 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, + uri, }: { assetId?: number; limit?: number; @@ -237,6 +248,7 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId?: string; timestampGte?: string; timestampLte?: string; + uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, @@ -254,6 +266,7 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, + uri, }, queryKey, ), @@ -269,6 +282,7 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, + uri, }) as TData, ...options, }); @@ -278,6 +292,7 @@ export const useAssetServiceGetAssetEvents = < * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -289,16 +304,18 @@ export const useAssetServiceGetAssetQueuedEvents = < { assetId, before, + uri, }: { assetId: number; before?: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }, queryKey), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }) as TData, + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }, queryKey), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }) as TData, ...options, }); /** @@ -306,6 +323,7 @@ export const useAssetServiceGetAssetQueuedEvents = < * Get an asset. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -316,15 +334,17 @@ export const useAssetServiceGetAsset = < >( { assetId, + uri, }: { assetId: number; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }, queryKey), - queryFn: () => AssetService.getAsset({ assetId }) as TData, + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }, queryKey), + queryFn: () => AssetService.getAsset({ assetId, uri }) as TData, ...options, }); /** @@ -333,6 +353,7 @@ export const useAssetServiceGetAsset = < * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -344,16 +365,18 @@ export const useAssetServiceGetDagAssetQueuedEvents = < { before, dagId, + uri, }: { before?: string; dagId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }) as TData, ...options, }); /** @@ -363,6 +386,7 @@ export const useAssetServiceGetDagAssetQueuedEvents = < * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -375,17 +399,19 @@ export const useAssetServiceGetDagAssetQueuedEvent = < assetId, before, dagId, + uri, }: { assetId: number; before?: string; dagId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }) as TData, ...options, }); /** @@ -2888,6 +2914,7 @@ export const useLoginServiceLogin = < * Create asset events. * @param data The data for the request. * @param data.requestBody + * @param data.uri * @returns AssetEventResponse Successful Response * @throws ApiError */ @@ -2902,6 +2929,7 @@ export const useAssetServiceCreateAssetEvent = < TError, { requestBody: CreateAssetEventsBody; + uri?: string; }, TContext >, @@ -2913,11 +2941,12 @@ export const useAssetServiceCreateAssetEvent = < TError, { requestBody: CreateAssetEventsBody; + uri?: string; }, TContext >({ - mutationFn: ({ requestBody }) => - AssetService.createAssetEvent({ requestBody }) as unknown as Promise, + mutationFn: ({ requestBody, uri }) => + AssetService.createAssetEvent({ requestBody, uri }) as unknown as Promise, ...options, }); /** @@ -2925,6 +2954,7 @@ export const useAssetServiceCreateAssetEvent = < * Materialize an asset by triggering a DAG run that produces it. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns DAGRunResponse Successful Response * @throws ApiError */ @@ -2939,6 +2969,7 @@ export const useAssetServiceMaterializeAsset = < TError, { assetId: number; + uri?: string; }, TContext >, @@ -2950,10 +2981,12 @@ export const useAssetServiceMaterializeAsset = < TError, { assetId: number; + uri?: string; }, TContext >({ - mutationFn: ({ assetId }) => AssetService.materializeAsset({ assetId }) as unknown as Promise, + mutationFn: ({ assetId, uri }) => + AssetService.materializeAsset({ assetId, uri }) as unknown as Promise, ...options, }); /** @@ -4316,6 +4349,7 @@ export const useVariableServiceBulkVariables = < * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -4331,6 +4365,7 @@ export const useAssetServiceDeleteAssetQueuedEvents = < { assetId: number; before?: string; + uri?: string; }, TContext >, @@ -4343,11 +4378,12 @@ export const useAssetServiceDeleteAssetQueuedEvents = < { assetId: number; before?: string; + uri?: string; }, TContext >({ - mutationFn: ({ assetId, before }) => - AssetService.deleteAssetQueuedEvents({ assetId, before }) as unknown as Promise, + mutationFn: ({ assetId, before, uri }) => + AssetService.deleteAssetQueuedEvents({ assetId, before, uri }) as unknown as Promise, ...options, }); /** @@ -4355,6 +4391,7 @@ export const useAssetServiceDeleteAssetQueuedEvents = < * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -4370,6 +4407,7 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < { before?: string; dagId: string; + uri?: string; }, TContext >, @@ -4382,11 +4420,12 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < { before?: string; dagId: string; + uri?: string; }, TContext >({ - mutationFn: ({ before, dagId }) => - AssetService.deleteDagAssetQueuedEvents({ before, dagId }) as unknown as Promise, + mutationFn: ({ before, dagId, uri }) => + AssetService.deleteDagAssetQueuedEvents({ before, dagId, uri }) as unknown as Promise, ...options, }); /** @@ -4396,6 +4435,7 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -4412,6 +4452,7 @@ export const useAssetServiceDeleteDagAssetQueuedEvent = < assetId: number; before?: string; dagId: string; + uri?: string; }, TContext >, @@ -4425,11 +4466,12 @@ export const useAssetServiceDeleteDagAssetQueuedEvent = < assetId: number; before?: string; dagId: string; + uri?: string; }, TContext >({ - mutationFn: ({ assetId, before, dagId }) => - AssetService.deleteDagAssetQueuedEvent({ assetId, before, dagId }) as unknown as Promise, + mutationFn: ({ assetId, before, dagId, uri }) => + AssetService.deleteDagAssetQueuedEvent({ assetId, before, dagId, uri }) as unknown as Promise, ...options, }); /** diff --git a/airflow/ui/openapi-gen/queries/suspense.ts b/airflow/ui/openapi-gen/queries/suspense.ts index 6c89053408a69..d7831c7070578 100644 --- a/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow/ui/openapi-gen/queries/suspense.ts @@ -113,6 +113,7 @@ export const useAssetServiceGetAssetsSuspense = < * Get Asset Aliases * Get asset aliases. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -130,18 +131,23 @@ export const useAssetServiceGetAssetAliasesSuspense = < namePattern, offset, orderBy, + uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; + uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn( + { limit, namePattern, offset, orderBy, uri }, + queryKey, + ), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }) as TData, ...options, }); /** @@ -149,6 +155,7 @@ export const useAssetServiceGetAssetAliasesSuspense = < * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId + * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -159,21 +166,24 @@ export const useAssetServiceGetAssetAliasSuspense = < >( { assetAliasId, + uri, }: { assetAliasId: number; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }, queryKey), - queryFn: () => AssetService.getAssetAlias({ assetAliasId }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }, queryKey), + queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }) as TData, ...options, }); /** * Get Asset Events * Get asset events. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.orderBy @@ -203,6 +213,7 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, + uri, }: { assetId?: number; limit?: number; @@ -214,6 +225,7 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId?: string; timestampGte?: string; timestampLte?: string; + uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, @@ -231,6 +243,7 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, + uri, }, queryKey, ), @@ -246,6 +259,7 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, + uri, }) as TData, ...options, }); @@ -255,6 +269,7 @@ export const useAssetServiceGetAssetEventsSuspense = < * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -266,16 +281,18 @@ export const useAssetServiceGetAssetQueuedEventsSuspense = < { assetId, before, + uri, }: { assetId: number; before?: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }, queryKey), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }) as TData, + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }, queryKey), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }) as TData, ...options, }); /** @@ -283,6 +300,7 @@ export const useAssetServiceGetAssetQueuedEventsSuspense = < * Get an asset. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -293,15 +311,17 @@ export const useAssetServiceGetAssetSuspense = < >( { assetId, + uri, }: { assetId: number; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }, queryKey), - queryFn: () => AssetService.getAsset({ assetId }) as TData, + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }, queryKey), + queryFn: () => AssetService.getAsset({ assetId, uri }) as TData, ...options, }); /** @@ -310,6 +330,7 @@ export const useAssetServiceGetAssetSuspense = < * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -321,16 +342,18 @@ export const useAssetServiceGetDagAssetQueuedEventsSuspense = < { before, dagId, + uri, }: { before?: string; dagId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }) as TData, ...options, }); /** @@ -340,6 +363,7 @@ export const useAssetServiceGetDagAssetQueuedEventsSuspense = < * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -352,17 +376,19 @@ export const useAssetServiceGetDagAssetQueuedEventSuspense = < assetId, before, dagId, + uri, }: { assetId: number; before?: string; dagId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index db3eeefa3b668..9212323a1e14c 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -272,6 +272,7 @@ export class AssetService { * Get Asset Aliases * Get asset aliases. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -284,6 +285,7 @@ export class AssetService { method: "GET", url: "/public/assets/aliases", query: { + uri: data.uri, limit: data.limit, offset: data.offset, name_pattern: data.namePattern, @@ -303,6 +305,7 @@ export class AssetService { * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId + * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -313,6 +316,9 @@ export class AssetService { path: { asset_alias_id: data.assetAliasId, }, + query: { + uri: data.uri, + }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -326,6 +332,7 @@ export class AssetService { * Get Asset Events * Get asset events. * @param data The data for the request. + * @param data.uri * @param data.limit * @param data.offset * @param data.orderBy @@ -344,6 +351,7 @@ export class AssetService { method: "GET", url: "/public/assets/events", query: { + uri: data.uri, limit: data.limit, offset: data.offset, order_by: data.orderBy, @@ -369,6 +377,7 @@ export class AssetService { * Create asset events. * @param data The data for the request. * @param data.requestBody + * @param data.uri * @returns AssetEventResponse Successful Response * @throws ApiError */ @@ -376,6 +385,9 @@ export class AssetService { return __request(OpenAPI, { method: "POST", url: "/public/assets/events", + query: { + uri: data.uri, + }, body: data.requestBody, mediaType: "application/json", errors: { @@ -392,6 +404,7 @@ export class AssetService { * Materialize an asset by triggering a DAG run that produces it. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns DAGRunResponse Successful Response * @throws ApiError */ @@ -402,6 +415,9 @@ export class AssetService { path: { asset_id: data.assetId, }, + query: { + uri: data.uri, + }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -418,6 +434,7 @@ export class AssetService { * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -432,6 +449,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 401: "Unauthorized", @@ -448,6 +466,7 @@ export class AssetService { * @param data The data for the request. * @param data.assetId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -462,6 +481,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 401: "Unauthorized", @@ -477,6 +497,7 @@ export class AssetService { * Get an asset. * @param data The data for the request. * @param data.assetId + * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -487,6 +508,9 @@ export class AssetService { path: { asset_id: data.assetId, }, + query: { + uri: data.uri, + }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -502,6 +526,7 @@ export class AssetService { * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -516,6 +541,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 401: "Unauthorized", @@ -531,6 +557,7 @@ export class AssetService { * @param data The data for the request. * @param data.dagId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -545,6 +572,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 400: "Bad Request", @@ -563,6 +591,7 @@ export class AssetService { * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -578,6 +607,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 401: "Unauthorized", @@ -595,6 +625,7 @@ export class AssetService { * @param data.dagId * @param data.assetId * @param data.before + * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -610,6 +641,7 @@ export class AssetService { }, query: { before: data.before, + uri: data.uri, }, errors: { 400: "Bad Request", diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index 0924a7922bc48..061d3c445079a 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1623,12 +1623,14 @@ export type GetAssetAliasesData = { namePattern?: string | null; offset?: number; orderBy?: string; + uri?: string | null; }; export type GetAssetAliasesResponse = AssetAliasCollectionResponse; export type GetAssetAliasData = { assetAliasId: number; + uri?: string | null; }; export type GetAssetAliasResponse = unknown; @@ -1644,18 +1646,21 @@ export type GetAssetEventsData = { sourceTaskId?: string | null; timestampGte?: string | null; timestampLte?: string | null; + uri?: string | null; }; export type GetAssetEventsResponse = AssetEventCollectionResponse; export type CreateAssetEventData = { requestBody: CreateAssetEventsBody; + uri?: string | null; }; export type CreateAssetEventResponse = AssetEventResponse; export type MaterializeAssetData = { assetId: number; + uri?: string | null; }; export type MaterializeAssetResponse = DAGRunResponse; @@ -1663,6 +1668,7 @@ export type MaterializeAssetResponse = DAGRunResponse; export type GetAssetQueuedEventsData = { assetId: number; before?: string | null; + uri?: string | null; }; export type GetAssetQueuedEventsResponse = QueuedEventCollectionResponse; @@ -1670,19 +1676,22 @@ export type GetAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteAssetQueuedEventsData = { assetId: number; before?: string | null; + uri?: string | null; }; export type DeleteAssetQueuedEventsResponse = void; export type GetAssetData = { assetId: number; + uri?: string | null; }; export type GetAssetResponse = AssetResponse; export type GetDagAssetQueuedEventsData = { before?: string | null; - dagId: string; + dagId: string | null; + uri?: string | null; }; export type GetDagAssetQueuedEventsResponse = QueuedEventCollectionResponse; @@ -1690,6 +1699,7 @@ export type GetDagAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteDagAssetQueuedEventsData = { before?: string | null; dagId: string; + uri?: string | null; }; export type DeleteDagAssetQueuedEventsResponse = void; @@ -1697,7 +1707,8 @@ export type DeleteDagAssetQueuedEventsResponse = void; export type GetDagAssetQueuedEventData = { assetId: number; before?: string | null; - dagId: string; + dagId: string | null; + uri?: string | null; }; export type GetDagAssetQueuedEventResponse = QueuedEventResponse; @@ -1706,6 +1717,7 @@ export type DeleteDagAssetQueuedEventData = { assetId: number; before?: string | null; dagId: string; + uri?: string | null; }; export type DeleteDagAssetQueuedEventResponse = void; diff --git a/tests/api_fastapi/core_api/routes/public/test_assets.py b/tests/api_fastapi/core_api/routes/public/test_assets.py index 7190e3b86eb6b..64d3b9868e07e 100644 --- a/tests/api_fastapi/core_api/routes/public/test_assets.py +++ b/tests/api_fastapi/core_api/routes/public/test_assets.py @@ -466,6 +466,10 @@ def test_should_respond_200(self, test_client, session): "total_entries": 2, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets/aliases") + assert response.status_code == 401 + def test_order_by_raises_400_for_invalid_attr(self, test_client, session): response = test_client.get("/public/assets/aliases?order_by=fake") @@ -598,6 +602,10 @@ def test_should_respond_200(self, test_client, session): "total_entries": 2, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets/events") + assert response.status_code == 401 + @pytest.mark.parametrize( "params, total_entries", [ @@ -791,6 +799,10 @@ def test_should_respond_200(self, test_client, session): "aliases": [], } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets/1") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/1") assert response.status_code == 404 @@ -827,6 +839,10 @@ def test_should_respond_200(self, test_client, session): assert response.status_code == 200 assert response.json() == {"id": 1, "name": "simple1", "group": "alias"} + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets/1") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/aliases/1") assert response.status_code == 404 @@ -866,6 +882,10 @@ def test_should_respond_200(self, test_client, session, create_dummy_dag): "total_entries": 1, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/dags/random/assets/queuedEvents") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): dag_id = "not_exists" @@ -897,6 +917,10 @@ def test_should_respond_204(self, test_client, session, create_dummy_dag): assert len(adrqs) == 0 check_last_log(session, dag_id=dag_id, event="delete_dag_asset_queued_events", logical_date=None) + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.delete("/public/dags/random/assets/queuedEvents") + assert response.status_code == 401 + def test_should_respond_404_invalid_dag(self, test_client): dag_id = "not_exists" @@ -945,6 +969,12 @@ def test_should_respond_200(self, test_client, session): } check_last_log(session, dag_id=None, event="create_asset_event", logical_date=None) + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.post( + "/public/assets/events", json={"asset_uri": "s3://bucket/key/1"} + ) + assert response.status_code == 401 + def test_invalid_attr_not_allowed(self, test_client, session): self.create_assets(session) event_invalid_payload = {"asset_uri": "s3://bucket/key/1", "extra": {"foo": "bar"}, "fake": {}} @@ -1018,6 +1048,10 @@ def test_should_respond_200(self, test_client): "note": None, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.post("/public/assets/2/materialize") + assert response.status_code == 401 + def test_should_respond_409_on_multiple_dags(self, test_client): response = test_client.post("/public/assets/2/materialize") assert response.status_code == 409 @@ -1051,6 +1085,10 @@ def test_should_respond_200(self, test_client, session, create_dummy_dag): "total_entries": 1, } + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get("/public/assets/1/queuedEvents") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/1/queuedEvents") assert response.status_code == 404 @@ -1072,6 +1110,10 @@ def test_should_respond_204(self, test_client, session, create_dummy_dag): assert session.get(AssetDagRunQueue, (asset_id, dag_id)) is None check_last_log(session, dag_id=None, event="delete_asset_queued_events", logical_date=None) + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.delete("/public/assets/1/queuedEvents") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): response = test_client.delete("/public/assets/1/queuedEvents") assert response.status_code == 404 @@ -1098,6 +1140,10 @@ def test_delete_should_respond_204(self, test_client, session, create_dummy_dag) assert len(adrq) == 0 check_last_log(session, dag_id=dag_id, event="delete_dag_asset_queued_event", logical_date=None) + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.delete("/public/dags/random/assets/random/queuedEvents") + assert response.status_code == 401 + def test_should_respond_404(self, test_client): dag_id = "not_exists" asset_id = 1 From 49768199edcc0605882ef23549807d4c848e9d16 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Thu, 27 Feb 2025 20:08:43 +0530 Subject: [PATCH 04/19] add commit session after creating dags --- tests/api_fastapi/core_api/routes/public/test_assets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/api_fastapi/core_api/routes/public/test_assets.py b/tests/api_fastapi/core_api/routes/public/test_assets.py index 64d3b9868e07e..224e21690cc4c 100644 --- a/tests/api_fastapi/core_api/routes/public/test_assets.py +++ b/tests/api_fastapi/core_api/routes/public/test_assets.py @@ -1024,6 +1024,7 @@ def create_dags(self, setup, dag_maker, session): EmptyOperator(task_id="task", outlets=assets[2]) with dag_maker(self.DAG_ASSET_NO, schedule=None, session=session): EmptyOperator(task_id="task") + session.commit() @pytest.mark.usefixtures("configure_git_connection_for_dag_bundle") def test_should_respond_200(self, test_client): From e3b411be65990916ca26fab00ce64bc39a82fa39 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Thu, 27 Feb 2025 23:05:44 +0530 Subject: [PATCH 05/19] fix issue with time_machine --- .../core_api/openapi/v1-generated.yaml | 10 ++ .../core_api/routes/public/dag_run.py | 2 + airflow/ui/openapi-gen/queries/common.ts | 4 +- airflow/ui/openapi-gen/queries/prefetch.ts | 7 +- airflow/ui/openapi-gen/queries/queries.ts | 7 +- airflow/ui/openapi-gen/queries/suspense.ts | 7 +- .../ui/openapi-gen/requests/services.gen.ts | 4 + airflow/ui/openapi-gen/requests/types.gen.ts | 1 + .../core_api/routes/public/test_dag_run.py | 133 +++++++++--------- 9 files changed, 105 insertions(+), 70 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index 51231cd79d1dd..30423314c4324 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -2334,6 +2334,8 @@ paths: description: If dag run is asset-triggered, return the asset events that triggered it. operationId: get_upstream_asset_events + security: + - OAuth2PasswordBearer: [] parameters: - name: dag_id in: path @@ -2347,6 +2349,14 @@ paths: schema: type: string title: Dag Run Id + - name: uri + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Uri responses: '200': description: Successful Response diff --git a/airflow/api_fastapi/core_api/routes/public/dag_run.py b/airflow/api_fastapi/core_api/routes/public/dag_run.py index fe278b5972666..8703fe42e423a 100644 --- a/airflow/api_fastapi/core_api/routes/public/dag_run.py +++ b/airflow/api_fastapi/core_api/routes/public/dag_run.py @@ -59,6 +59,7 @@ TaskInstanceResponse, ) from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc +from airflow.api_fastapi.core_api.security import requires_access_asset from airflow.api_fastapi.logging.decorators import action_logging from airflow.exceptions import ParamValidationError from airflow.listeners.listener import get_listener_manager @@ -189,6 +190,7 @@ def patch_dag_run( status.HTTP_404_NOT_FOUND, ] ), + dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_upstream_asset_events( dag_id: str, dag_run_id: str, session: SessionDep diff --git a/airflow/ui/openapi-gen/queries/common.ts b/airflow/ui/openapi-gen/queries/common.ts index 8ee7ccd27049a..a6efb801aad51 100644 --- a/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow/ui/openapi-gen/queries/common.ts @@ -596,12 +596,14 @@ export const UseDagRunServiceGetUpstreamAssetEventsKeyFn = ( { dagId, dagRunId, + uri, }: { dagId: string; dagRunId: string; + uri?: string; }, queryKey?: Array, -) => [useDagRunServiceGetUpstreamAssetEventsKey, ...(queryKey ?? [{ dagId, dagRunId }])]; +) => [useDagRunServiceGetUpstreamAssetEventsKey, ...(queryKey ?? [{ dagId, dagRunId, uri }])]; export type DagRunServiceGetDagRunsDefaultResponse = Awaited>; export type DagRunServiceGetDagRunsQueryResult< TData = DagRunServiceGetDagRunsDefaultResponse, diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow/ui/openapi-gen/queries/prefetch.ts index 564565dd14f23..06e7e0f817859 100644 --- a/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow/ui/openapi-gen/queries/prefetch.ts @@ -803,6 +803,7 @@ export const prefetchUseDagRunServiceGetDagRun = ( * @param data The data for the request. * @param data.dagId * @param data.dagRunId + * @param data.uri * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -811,14 +812,16 @@ export const prefetchUseDagRunServiceGetUpstreamAssetEvents = ( { dagId, dagRunId, + uri, }: { dagId: string; dagRunId: string; + uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId }), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId }), + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }), + queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }), }); /** * Get Dag Runs diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index cef95a984695e..a58cf591fbae0 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -973,6 +973,7 @@ export const useDagRunServiceGetDagRun = < * @param data The data for the request. * @param data.dagId * @param data.dagRunId + * @param data.uri * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -984,16 +985,18 @@ export const useDagRunServiceGetUpstreamAssetEvents = < { dagId, dagRunId, + uri, }: { dagId: string; dagRunId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId }, queryKey), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId }) as TData, + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }, queryKey), + queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/queries/suspense.ts b/airflow/ui/openapi-gen/queries/suspense.ts index d7831c7070578..b4e2fca28ab07 100644 --- a/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow/ui/openapi-gen/queries/suspense.ts @@ -950,6 +950,7 @@ export const useDagRunServiceGetDagRunSuspense = < * @param data The data for the request. * @param data.dagId * @param data.dagRunId + * @param data.uri * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -961,16 +962,18 @@ export const useDagRunServiceGetUpstreamAssetEventsSuspense = < { dagId, dagRunId, + uri, }: { dagId: string; dagRunId: string; + uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId }, queryKey), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId }) as TData, + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }, queryKey), + queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index 9212323a1e14c..082c63330fef9 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -1403,6 +1403,7 @@ export class DagRunService { * @param data The data for the request. * @param data.dagId * @param data.dagRunId + * @param data.uri * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -1416,6 +1417,9 @@ export class DagRunService { dag_id: data.dagId, dag_run_id: data.dagRunId, }, + query: { + uri: data.uri, + }, errors: { 401: "Unauthorized", 403: "Forbidden", diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index 2a98ce242c0ff..dc0ff4c92941f 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1936,6 +1936,7 @@ export type PatchDagRunResponse = DAGRunResponse; export type GetUpstreamAssetEventsData = { dagId: string; dagRunId: string; + uri?: string | null; }; export type GetUpstreamAssetEventsResponse = AssetEventCollectionResponse; diff --git a/tests/api_fastapi/core_api/routes/public/test_dag_run.py b/tests/api_fastapi/core_api/routes/public/test_dag_run.py index f12cab28468ff..a9fe36e09345d 100644 --- a/tests/api_fastapi/core_api/routes/public/test_dag_run.py +++ b/tests/api_fastapi/core_api/routes/public/test_dag_run.py @@ -1073,6 +1073,12 @@ def test_should_respond_200(self, test_client, dag_maker, session): } assert response.json() == expected_response + def test_should_respond_401(self, unauthenticated_test_client): + response = unauthenticated_test_client.get( + "/public/dags/TEST_DAG_ID/dagRuns/TEST_DAG_RUN_ID/upstreamAssetEvents", + ) + assert response.status_code == 401 + def test_should_respond_404(self, test_client): response = test_client.get( "public/dags/invalid-id/dagRuns/invalid-run-id/upstreamAssetEvents", @@ -1163,7 +1169,6 @@ def _dags_for_trigger_tests(self, session=None): session.add(import_errors_dag) session.commit() - @time_machine.travel(timezone.utcnow(), tick=False) @pytest.mark.parametrize( "dag_run_id, note, data_interval_start, data_interval_end", [ @@ -1181,59 +1186,61 @@ def _dags_for_trigger_tests(self, session=None): def test_should_respond_200( self, test_client, dag_run_id, note, data_interval_start, data_interval_end, session ): - fixed_now = timezone.utcnow().isoformat() - - request_json = {"note": note, "logical_date": fixed_now} - if dag_run_id is not None: - request_json["dag_run_id"] = dag_run_id - if data_interval_start is not None: - request_json["data_interval_start"] = data_interval_start - if data_interval_end is not None: - request_json["data_interval_end"] = data_interval_end - request_json["logical_date"] = fixed_now - - response = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json=request_json, - ) - assert response.status_code == 200 + with time_machine.travel(timezone.utcnow(), tick=False): + fixed_now = timezone.utcnow().isoformat() + + request_json = {"note": note, "logical_date": fixed_now} + if dag_run_id is not None: + request_json["dag_run_id"] = dag_run_id + if data_interval_start is not None: + request_json["data_interval_start"] = data_interval_start + if data_interval_end is not None: + request_json["data_interval_end"] = data_interval_end + request_json["logical_date"] = fixed_now + response = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json=request_json, + ) + assert response.status_code == 200 - if dag_run_id is None: - expected_dag_run_id = f"manual__{fixed_now}" - else: - expected_dag_run_id = dag_run_id + if dag_run_id is None: + expected_dag_run_id = f"manual__{fixed_now}" + else: + expected_dag_run_id = dag_run_id - expected_data_interval_start = fixed_now.replace("+00:00", "Z") - expected_data_interval_end = fixed_now.replace("+00:00", "Z") - if data_interval_start is not None and data_interval_end is not None: - expected_data_interval_start = data_interval_start.replace("+00:00", "Z") - expected_data_interval_end = data_interval_end.replace("+00:00", "Z") - expected_logical_date = fixed_now.replace("+00:00", "Z") + expected_data_interval_start = fixed_now.replace("+00:00", "Z") + expected_data_interval_end = fixed_now.replace("+00:00", "Z") + if data_interval_start is not None and data_interval_end is not None: + expected_data_interval_start = data_interval_start.replace("+00:00", "Z") + expected_data_interval_end = data_interval_end.replace("+00:00", "Z") + expected_logical_date = fixed_now.replace("+00:00", "Z") - run = ( - session.query(DagRun).where(DagRun.dag_id == DAG1_ID, DagRun.run_id == expected_dag_run_id).one() - ) - expected_response_json = { - "conf": {}, - "dag_id": DAG1_ID, - "dag_run_id": expected_dag_run_id, - "dag_versions": get_dag_versions_dict(run.dag_versions), - "end_date": None, - "logical_date": expected_logical_date, - "run_after": fixed_now.replace("+00:00", "Z"), - "start_date": None, - "state": "queued", - "data_interval_end": expected_data_interval_end, - "data_interval_start": expected_data_interval_start, - "queued_at": fixed_now.replace("+00:00", "Z"), - "last_scheduling_decision": None, - "run_type": "manual", - "note": note, - "triggered_by": "rest_api", - } + run = ( + session.query(DagRun) + .where(DagRun.dag_id == DAG1_ID, DagRun.run_id == expected_dag_run_id) + .one() + ) + expected_response_json = { + "conf": {}, + "dag_id": DAG1_ID, + "dag_run_id": expected_dag_run_id, + "dag_versions": get_dag_versions_dict(run.dag_versions), + "end_date": None, + "logical_date": expected_logical_date, + "run_after": fixed_now.replace("+00:00", "Z"), + "start_date": None, + "state": "queued", + "data_interval_end": expected_data_interval_end, + "data_interval_start": expected_data_interval_start, + "queued_at": fixed_now.replace("+00:00", "Z"), + "last_scheduling_decision": None, + "run_type": "manual", + "note": note, + "triggered_by": "rest_api", + } - assert response.json() == expected_response_json - _check_last_log(session, dag_id=DAG1_ID, event="trigger_dag_run", logical_date=None) + assert response.json() == expected_response_json + _check_last_log(session, dag_id=DAG1_ID, event="trigger_dag_run", logical_date=None) @pytest.mark.parametrize( "post_body, expected_detail", @@ -1353,21 +1360,21 @@ def test_should_respond_400_if_a_dag_has_import_errors(self, test_client, sessio == "DAG with dag_id: 'import_errors' has import errors and cannot be triggered" ) - @time_machine.travel(timezone.utcnow(), tick=False) @pytest.mark.usefixtures("configure_git_connection_for_dag_bundle") def test_should_response_409_for_duplicate_logical_date(self, test_client): - RUN_ID_1 = "random_1" - RUN_ID_2 = "random_2" - now = timezone.utcnow().isoformat().replace("+00:00", "Z") - note = "duplicate logical date test" - response_1 = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json={"dag_run_id": RUN_ID_1, "note": note, "logical_date": now}, - ) - response_2 = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json={"dag_run_id": RUN_ID_2, "note": note, "logical_date": now}, - ) + with time_machine.travel(timezone.utcnow(), tick=False): + RUN_ID_1 = "random_1" + RUN_ID_2 = "random_2" + now = timezone.utcnow().isoformat().replace("+00:00", "Z") + note = "duplicate logical date test" + response_1 = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json={"dag_run_id": RUN_ID_1, "note": note, "logical_date": now}, + ) + response_2 = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json={"dag_run_id": RUN_ID_2, "note": note, "logical_date": now}, + ) assert response_1.status_code == 200 assert response_1.json() == { From 39a35b14f0372310b82b430a468827889569539b Mon Sep 17 00:00:00 2001 From: kalyanr Date: Thu, 27 Feb 2025 23:33:38 +0530 Subject: [PATCH 06/19] session commit in make_dag_with_multiple_versions --- tests/api_fastapi/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index fd5df6efa7ec1..102c59c844794 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -93,7 +93,7 @@ def configure_git_connection_for_dag_bundle(session): @pytest.fixture -def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_bundle): +def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_bundle, session): """ Create DAG with multiple versions @@ -103,7 +103,6 @@ def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_ """ dag_id = "dag_with_multiple_versions" - for version_number in range(1, 4): with dag_maker(dag_id) as dag: for task_number in range(version_number): @@ -117,6 +116,7 @@ def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_ logical_date=datetime.datetime(2020, 1, version_number, tzinfo=datetime.timezone.utc), dag_version=DagVersion.get_version(dag_id=dag_id, version_number=version_number), ) + session.commit() @pytest.fixture(scope="module") From 1183e2090c373b092d34d1cd2188e1a32f00e87c Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 00:28:48 +0530 Subject: [PATCH 07/19] fix ci failure --- task_sdk/src/airflow/sdk/api/datamodels/_generated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_sdk/src/airflow/sdk/api/datamodels/_generated.py b/task_sdk/src/airflow/sdk/api/datamodels/_generated.py index 4db100e8b42f8..b4504e154ef8b 100644 --- a/task_sdk/src/airflow/sdk/api/datamodels/_generated.py +++ b/task_sdk/src/airflow/sdk/api/datamodels/_generated.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: http://0.0.0.0:9091/execution/openapi.json -# version: 0.28.1 +# version: 0.28.2 # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file From 67b009ba9a81d8b699f9a72c57b8815104c36885 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 08:36:05 +0530 Subject: [PATCH 08/19] add unauthorized user tests --- tests/api_fastapi/conftest.py | 17 ++++++ .../core_api/routes/public/test_assets.py | 52 ++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index 102c59c844794..857bc120fd61d 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -56,6 +56,23 @@ def unauthenticated_test_client(): return TestClient(create_app()) +@pytest.fixture +def unauthorized_test_client(): + with conf_vars( + { + ( + "core", + "auth_manager", + ): "airflow.auth.managers.simple.simple_auth_manager.SimpleAuthManager", + } + ): + auth_manager = SimpleAuthManager() + token = auth_manager._get_token_signer().generate_signed_token( + auth_manager.serialize_user(SimpleAuthManagerUser(username="dummy", role=None)) + ) + yield TestClient(create_app(), headers={"Authorization": f"Bearer {token}"}) + + @pytest.fixture def client(): """This fixture is more flexible than test_client, as it allows to specify which apps to include.""" diff --git a/tests/api_fastapi/core_api/routes/public/test_assets.py b/tests/api_fastapi/core_api/routes/public/test_assets.py index 224e21690cc4c..86bd397595498 100644 --- a/tests/api_fastapi/core_api/routes/public/test_assets.py +++ b/tests/api_fastapi/core_api/routes/public/test_assets.py @@ -267,6 +267,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/assets") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets") + assert response.status_code == 403 + def test_order_by_raises_400_for_invalid_attr(self, test_client, session): response = test_client.get("/public/assets?order_by=fake") @@ -470,6 +474,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/assets/aliases") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets/aliases") + assert response.status_code == 403 + def test_order_by_raises_400_for_invalid_attr(self, test_client, session): response = test_client.get("/public/assets/aliases?order_by=fake") @@ -606,6 +614,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/assets/events") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets/events") + assert response.status_code == 403 + @pytest.mark.parametrize( "params, total_entries", [ @@ -803,6 +815,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/assets/1") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets/1") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/1") assert response.status_code == 404 @@ -840,9 +856,13 @@ def test_should_respond_200(self, test_client, session): assert response.json() == {"id": 1, "name": "simple1", "group": "alias"} def test_should_respond_401(self, unauthenticated_test_client): - response = unauthenticated_test_client.get("/public/assets/1") + response = unauthenticated_test_client.get("/public/assets/aliases/1") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets/1") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/aliases/1") assert response.status_code == 404 @@ -886,6 +906,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/dags/random/assets/queuedEvents") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/dags/random/assets/queuedEvents") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): dag_id = "not_exists" @@ -921,6 +945,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.delete("/public/dags/random/assets/queuedEvents") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/dags/random/assets/queuedEvents") + assert response.status_code == 403 + def test_should_respond_404_invalid_dag(self, test_client): dag_id = "not_exists" @@ -975,6 +1003,12 @@ def test_should_respond_401(self, unauthenticated_test_client): ) assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.post( + "/public/assets/events", json={"asset_uri": "s3://bucket/key/1"} + ) + assert response.status_code == 403 + def test_invalid_attr_not_allowed(self, test_client, session): self.create_assets(session) event_invalid_payload = {"asset_uri": "s3://bucket/key/1", "extra": {"foo": "bar"}, "fake": {}} @@ -1053,6 +1087,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.post("/public/assets/2/materialize") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.post("/public/assets/2/materialize") + assert response.status_code == 403 + def test_should_respond_409_on_multiple_dags(self, test_client): response = test_client.post("/public/assets/2/materialize") assert response.status_code == 409 @@ -1090,6 +1128,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get("/public/assets/1/queuedEvents") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get("/public/assets/1/queuedEvents") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/1/queuedEvents") assert response.status_code == 404 @@ -1115,6 +1157,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.delete("/public/assets/1/queuedEvents") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.delete("/public/assets/1/queuedEvents") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): response = test_client.delete("/public/assets/1/queuedEvents") assert response.status_code == 404 @@ -1145,6 +1191,10 @@ def test_should_respond_401(self, unauthenticated_test_client): response = unauthenticated_test_client.delete("/public/dags/random/assets/random/queuedEvents") assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.delete("/public/dags/random/assets/random/queuedEvents") + assert response.status_code == 403 + def test_should_respond_404(self, test_client): dag_id = "not_exists" asset_id = 1 From c5e805ba8c0e7fe8c5c048ff6b12d01e1ed52ec5 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 10:12:19 +0530 Subject: [PATCH 09/19] fix --- tests/api_fastapi/conftest.py | 11 +- .../core_api/routes/public/test_dag_run.py | 126 +++++++++--------- 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index 857bc120fd61d..1a9921e6347a5 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -45,8 +45,17 @@ def test_client(): } ): auth_manager = SimpleAuthManager() + # set time_very_before to 2014-01-01 00:00:00 and time_very_after to tomorrow + # to make the JWT token always valid for all test cases with time_machine + time_very_before = datetime.datetime(2014, 1, 1, 0, 0, 0) + time_very_after = datetime.datetime.now() + datetime.timedelta(days=1) token = auth_manager._get_token_signer().generate_signed_token( - auth_manager.serialize_user(SimpleAuthManagerUser(username="test", role="admin")) + { + "iat": time_very_before, + "nbf": time_very_before, + "exp": time_very_after, + **auth_manager.serialize_user(SimpleAuthManagerUser(username="test", role="admin")), + } ) yield TestClient(create_app(), headers={"Authorization": f"Bearer {token}"}) diff --git a/tests/api_fastapi/core_api/routes/public/test_dag_run.py b/tests/api_fastapi/core_api/routes/public/test_dag_run.py index a9fe36e09345d..71a274a7a7062 100644 --- a/tests/api_fastapi/core_api/routes/public/test_dag_run.py +++ b/tests/api_fastapi/core_api/routes/public/test_dag_run.py @@ -1169,6 +1169,7 @@ def _dags_for_trigger_tests(self, session=None): session.add(import_errors_dag) session.commit() + @time_machine.travel(timezone.utcnow(), tick=False) @pytest.mark.parametrize( "dag_run_id, note, data_interval_start, data_interval_end", [ @@ -1186,61 +1187,58 @@ def _dags_for_trigger_tests(self, session=None): def test_should_respond_200( self, test_client, dag_run_id, note, data_interval_start, data_interval_end, session ): - with time_machine.travel(timezone.utcnow(), tick=False): - fixed_now = timezone.utcnow().isoformat() - - request_json = {"note": note, "logical_date": fixed_now} - if dag_run_id is not None: - request_json["dag_run_id"] = dag_run_id - if data_interval_start is not None: - request_json["data_interval_start"] = data_interval_start - if data_interval_end is not None: - request_json["data_interval_end"] = data_interval_end - request_json["logical_date"] = fixed_now - response = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json=request_json, - ) - assert response.status_code == 200 + fixed_now = timezone.utcnow().isoformat() + + request_json = {"note": note, "logical_date": fixed_now} + if dag_run_id is not None: + request_json["dag_run_id"] = dag_run_id + if data_interval_start is not None: + request_json["data_interval_start"] = data_interval_start + if data_interval_end is not None: + request_json["data_interval_end"] = data_interval_end + request_json["logical_date"] = fixed_now + response = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json=request_json, + ) + assert response.status_code == 200 - if dag_run_id is None: - expected_dag_run_id = f"manual__{fixed_now}" - else: - expected_dag_run_id = dag_run_id + if dag_run_id is None: + expected_dag_run_id = f"manual__{fixed_now}" + else: + expected_dag_run_id = dag_run_id - expected_data_interval_start = fixed_now.replace("+00:00", "Z") - expected_data_interval_end = fixed_now.replace("+00:00", "Z") - if data_interval_start is not None and data_interval_end is not None: - expected_data_interval_start = data_interval_start.replace("+00:00", "Z") - expected_data_interval_end = data_interval_end.replace("+00:00", "Z") - expected_logical_date = fixed_now.replace("+00:00", "Z") + expected_data_interval_start = fixed_now.replace("+00:00", "Z") + expected_data_interval_end = fixed_now.replace("+00:00", "Z") + if data_interval_start is not None and data_interval_end is not None: + expected_data_interval_start = data_interval_start.replace("+00:00", "Z") + expected_data_interval_end = data_interval_end.replace("+00:00", "Z") + expected_logical_date = fixed_now.replace("+00:00", "Z") - run = ( - session.query(DagRun) - .where(DagRun.dag_id == DAG1_ID, DagRun.run_id == expected_dag_run_id) - .one() - ) - expected_response_json = { - "conf": {}, - "dag_id": DAG1_ID, - "dag_run_id": expected_dag_run_id, - "dag_versions": get_dag_versions_dict(run.dag_versions), - "end_date": None, - "logical_date": expected_logical_date, - "run_after": fixed_now.replace("+00:00", "Z"), - "start_date": None, - "state": "queued", - "data_interval_end": expected_data_interval_end, - "data_interval_start": expected_data_interval_start, - "queued_at": fixed_now.replace("+00:00", "Z"), - "last_scheduling_decision": None, - "run_type": "manual", - "note": note, - "triggered_by": "rest_api", - } + run = ( + session.query(DagRun).where(DagRun.dag_id == DAG1_ID, DagRun.run_id == expected_dag_run_id).one() + ) + expected_response_json = { + "conf": {}, + "dag_id": DAG1_ID, + "dag_run_id": expected_dag_run_id, + "dag_versions": get_dag_versions_dict(run.dag_versions), + "end_date": None, + "logical_date": expected_logical_date, + "run_after": fixed_now.replace("+00:00", "Z"), + "start_date": None, + "state": "queued", + "data_interval_end": expected_data_interval_end, + "data_interval_start": expected_data_interval_start, + "queued_at": fixed_now.replace("+00:00", "Z"), + "last_scheduling_decision": None, + "run_type": "manual", + "note": note, + "triggered_by": "rest_api", + } - assert response.json() == expected_response_json - _check_last_log(session, dag_id=DAG1_ID, event="trigger_dag_run", logical_date=None) + assert response.json() == expected_response_json + _check_last_log(session, dag_id=DAG1_ID, event="trigger_dag_run", logical_date=None) @pytest.mark.parametrize( "post_body, expected_detail", @@ -1360,21 +1358,21 @@ def test_should_respond_400_if_a_dag_has_import_errors(self, test_client, sessio == "DAG with dag_id: 'import_errors' has import errors and cannot be triggered" ) + @time_machine.travel(timezone.utcnow(), tick=False) @pytest.mark.usefixtures("configure_git_connection_for_dag_bundle") def test_should_response_409_for_duplicate_logical_date(self, test_client): - with time_machine.travel(timezone.utcnow(), tick=False): - RUN_ID_1 = "random_1" - RUN_ID_2 = "random_2" - now = timezone.utcnow().isoformat().replace("+00:00", "Z") - note = "duplicate logical date test" - response_1 = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json={"dag_run_id": RUN_ID_1, "note": note, "logical_date": now}, - ) - response_2 = test_client.post( - f"/public/dags/{DAG1_ID}/dagRuns", - json={"dag_run_id": RUN_ID_2, "note": note, "logical_date": now}, - ) + RUN_ID_1 = "random_1" + RUN_ID_2 = "random_2" + now = timezone.utcnow().isoformat().replace("+00:00", "Z") + note = "duplicate logical date test" + response_1 = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json={"dag_run_id": RUN_ID_1, "note": note, "logical_date": now}, + ) + response_2 = test_client.post( + f"/public/dags/{DAG1_ID}/dagRuns", + json={"dag_run_id": RUN_ID_2, "note": note, "logical_date": now}, + ) assert response_1.status_code == 200 assert response_1.json() == { From f1b9de14a89799c510a40031e50771b9247971e6 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 18:29:44 +0530 Subject: [PATCH 10/19] fix --- airflow/api_fastapi/core_api/security.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow/api_fastapi/core_api/security.py b/airflow/api_fastapi/core_api/security.py index 45c6730a130ec..95fc35023c6c8 100644 --- a/airflow/api_fastapi/core_api/security.py +++ b/airflow/api_fastapi/core_api/security.py @@ -88,7 +88,7 @@ def inner( user: Annotated[BaseUser | None, Depends(get_user)] = None, ) -> None: def callback(): - return get_auth_manager().is_authorized_dag( + return get_auth_manager().is_authorized_asset( method=method, details=AssetDetails(uri=uri), user=user ) From eb92a9017ead41340f1517f439af1bc4bcd205d4 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 22:31:25 +0530 Subject: [PATCH 11/19] move dag.sync_to_db to end --- tests/api_fastapi/conftest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index 1a9921e6347a5..cfe7e1f7d5cf4 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -133,7 +133,6 @@ def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_ with dag_maker(dag_id) as dag: for task_number in range(version_number): EmptyOperator(task_id=f"task{task_number + 1}") - dag.sync_to_db() SerializedDagModel.write_dag( dag, bundle_name="dag_maker", bundle_version=f"some_commit_hash{version_number}" ) @@ -142,7 +141,7 @@ def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_ logical_date=datetime.datetime(2020, 1, version_number, tzinfo=datetime.timezone.utc), dag_version=DagVersion.get_version(dag_id=dag_id, version_number=version_number), ) - session.commit() + dag.sync_to_db() @pytest.fixture(scope="module") From 978b9cb074e75d2f3f494a014840c7e1eee3544c Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 23:00:38 +0530 Subject: [PATCH 12/19] pr feedback --- .../api_fastapi/core_api/openapi/v1-generated.yaml | 12 +++++++++++- airflow/api_fastapi/core_api/routes/public/assets.py | 12 ++++++++++-- airflow/ui/openapi-gen/queries/queries.ts | 7 +++++-- airflow/ui/openapi-gen/requests/services.gen.ts | 2 ++ airflow/ui/openapi-gen/requests/types.gen.ts | 3 ++- .../core_api/routes/public/test_dag_run.py | 6 ++++++ 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index 30423314c4324..675ae9dbd8e80 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -1090,6 +1090,14 @@ paths: - type: string - type: 'null' title: Uri + - name: dag_id + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + title: Dag Id responses: '204': description: Successful Response @@ -1249,7 +1257,9 @@ paths: in: path required: true schema: - type: string + anyOf: + - type: string + - type: 'null' title: Dag Id - name: before in: query diff --git a/airflow/api_fastapi/core_api/routes/public/assets.py b/airflow/api_fastapi/core_api/routes/public/assets.py index 382f049b04db8..4da875e46befb 100644 --- a/airflow/api_fastapi/core_api/routes/public/assets.py +++ b/airflow/api_fastapi/core_api/routes/public/assets.py @@ -422,7 +422,11 @@ def get_dag_asset_queued_event( "/assets/{asset_id}/queuedEvents", status_code=status.HTTP_204_NO_CONTENT, responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), - dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], + dependencies=[ + Depends(requires_access_asset(method="DELETE")), + Depends(requires_access_dag(method="GET")), + Depends(action_logging()), + ], ) def delete_asset_queued_events( asset_id: int, @@ -449,7 +453,11 @@ def delete_asset_queued_events( status.HTTP_404_NOT_FOUND, ] ), - dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], + dependencies=[ + Depends(requires_access_asset(method="DELETE")), + Depends(requires_access_dag(method="GET")), + Depends(action_logging()), + ], ) def delete_dag_asset_queued_events( dag_id: str, diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index a58cf591fbae0..c7479e2544516 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -4353,6 +4353,7 @@ export const useVariableServiceBulkVariables = < * @param data.assetId * @param data.before * @param data.uri + * @param data.dagId * @returns void Successful Response * @throws ApiError */ @@ -4368,6 +4369,7 @@ export const useAssetServiceDeleteAssetQueuedEvents = < { assetId: number; before?: string; + dagId?: string; uri?: string; }, TContext @@ -4381,12 +4383,13 @@ export const useAssetServiceDeleteAssetQueuedEvents = < { assetId: number; before?: string; + dagId?: string; uri?: string; }, TContext >({ - mutationFn: ({ assetId, before, uri }) => - AssetService.deleteAssetQueuedEvents({ assetId, before, uri }) as unknown as Promise, + mutationFn: ({ assetId, before, dagId, uri }) => + AssetService.deleteAssetQueuedEvents({ assetId, before, dagId, uri }) as unknown as Promise, ...options, }); /** diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index 082c63330fef9..3531bea7870ad 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -467,6 +467,7 @@ export class AssetService { * @param data.assetId * @param data.before * @param data.uri + * @param data.dagId * @returns void Successful Response * @throws ApiError */ @@ -482,6 +483,7 @@ export class AssetService { query: { before: data.before, uri: data.uri, + dag_id: data.dagId, }, errors: { 401: "Unauthorized", diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index dc0ff4c92941f..118811b2c14cd 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1685,6 +1685,7 @@ export type GetAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteAssetQueuedEventsData = { assetId: number; before?: string | null; + dagId?: string | null; uri?: string | null; }; @@ -1707,7 +1708,7 @@ export type GetDagAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteDagAssetQueuedEventsData = { before?: string | null; - dagId: string; + dagId: string | null; uri?: string | null; }; diff --git a/tests/api_fastapi/core_api/routes/public/test_dag_run.py b/tests/api_fastapi/core_api/routes/public/test_dag_run.py index 71a274a7a7062..f62bff0665ec6 100644 --- a/tests/api_fastapi/core_api/routes/public/test_dag_run.py +++ b/tests/api_fastapi/core_api/routes/public/test_dag_run.py @@ -1079,6 +1079,12 @@ def test_should_respond_401(self, unauthenticated_test_client): ) assert response.status_code == 401 + def test_should_respond_403(self, unauthorized_test_client): + response = unauthorized_test_client.get( + "/public/dags/TEST_DAG_ID/dagRuns/TEST_DAG_RUN_ID/upstreamAssetEvents" + ) + assert response.status_code == 403 + def test_should_respond_404(self, test_client): response = test_client.get( "public/dags/invalid-id/dagRuns/invalid-run-id/upstreamAssetEvents", From 92d6b1694da4b4660d6bbf1f0f4a21bd600a35a0 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Fri, 28 Feb 2025 23:20:39 +0530 Subject: [PATCH 13/19] fix --- airflow/api_fastapi/core_api/openapi/v1-generated.yaml | 4 +++- airflow/api_fastapi/core_api/routes/public/assets.py | 6 +++++- airflow/ui/openapi-gen/requests/types.gen.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index 675ae9dbd8e80..8a4265afea1b8 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -1394,7 +1394,9 @@ paths: in: path required: true schema: - type: string + anyOf: + - type: string + - type: 'null' title: Dag Id - name: asset_id in: path diff --git a/airflow/api_fastapi/core_api/routes/public/assets.py b/airflow/api_fastapi/core_api/routes/public/assets.py index 4da875e46befb..e0252d1634631 100644 --- a/airflow/api_fastapi/core_api/routes/public/assets.py +++ b/airflow/api_fastapi/core_api/routes/public/assets.py @@ -482,7 +482,11 @@ def delete_dag_asset_queued_events( status.HTTP_404_NOT_FOUND, ] ), - dependencies=[Depends(requires_access_asset(method="DELETE")), Depends(action_logging())], + dependencies=[ + Depends(requires_access_asset(method="DELETE")), + Depends(requires_access_dag(method="GET")), + Depends(action_logging()), + ], ) def delete_dag_asset_queued_event( dag_id: str, diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index 118811b2c14cd..820eefe724885 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1726,7 +1726,7 @@ export type GetDagAssetQueuedEventResponse = QueuedEventResponse; export type DeleteDagAssetQueuedEventData = { assetId: number; before?: string | null; - dagId: string; + dagId: string | null; uri?: string | null; }; From fd75ec20af59dbd4fd487f9c6215457290993cd7 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Sat, 1 Mar 2025 15:49:55 +0530 Subject: [PATCH 14/19] replace uri with id in AssetDetails --- .../core_api/openapi/v1-generated.yaml | 118 ++++------------ .../core_api/routes/public/assets.py | 2 - airflow/api_fastapi/core_api/security.py | 4 +- .../auth/managers/models/resource_details.py | 2 +- airflow/ui/openapi-gen/queries/common.ts | 47 +++---- airflow/ui/openapi-gen/queries/prefetch.ts | 79 ++++------- airflow/ui/openapi-gen/queries/queries.ts | 133 +++++++----------- airflow/ui/openapi-gen/queries/suspense.ts | 81 ++++------- .../ui/openapi-gen/requests/services.gen.ts | 48 ++----- airflow/ui/openapi-gen/requests/types.gen.ts | 31 ++-- .../aws/auth_manager/aws_auth_manager.py | 4 +- .../aws/auth_manager/test_aws_auth_manager.py | 2 +- 12 files changed, 182 insertions(+), 369 deletions(-) diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index 87f3df53ad4db..03acf2d4f0f6f 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -531,14 +531,14 @@ paths: security: - OAuth2PasswordBearer: [] parameters: - - name: uri + - name: asset_id in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id - name: limit in: query required: false @@ -624,17 +624,7 @@ paths: summary: Get Asset Aliases description: Get asset aliases. operationId: get_asset_aliases - security: - - OAuth2PasswordBearer: [] parameters: - - name: uri - in: query - required: false - schema: - anyOf: - - type: string - - type: 'null' - title: Uri - name: limit in: query required: false @@ -704,8 +694,6 @@ paths: summary: Get Asset Alias description: Get an asset alias. operationId: get_asset_alias - security: - - OAuth2PasswordBearer: [] parameters: - name: asset_alias_id in: path @@ -713,14 +701,6 @@ paths: schema: type: integer title: Asset Alias Id - - name: uri - in: query - required: false - schema: - anyOf: - - type: string - - type: 'null' - title: Uri responses: '200': description: Successful Response @@ -761,14 +741,14 @@ paths: security: - OAuth2PasswordBearer: [] parameters: - - name: uri + - name: asset_id in: query required: false schema: anyOf: - - type: string + - type: integer - type: 'null' - title: Uri + title: Asset Id - name: limit in: query required: false @@ -792,14 +772,6 @@ paths: type: string default: timestamp title: Order By - - name: asset_id - in: query - required: false - schema: - anyOf: - - type: integer - - type: 'null' - title: Asset Id - name: source_dag_id in: query required: false @@ -890,14 +862,14 @@ paths: security: - OAuth2PasswordBearer: [] parameters: - - name: uri + - name: asset_id in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id requestBody: required: true content: @@ -948,17 +920,11 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: uri - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id responses: '200': description: Successful Response @@ -1009,25 +975,19 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: before - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Before - - name: uri + title: Asset Id + - name: before in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Before responses: '200': description: Successful Response @@ -1071,25 +1031,19 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: before - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Before - - name: uri + title: Asset Id + - name: before in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Before - name: dag_id in: query required: false @@ -1138,17 +1092,11 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: uri - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id responses: '200': description: Successful Response @@ -1206,14 +1154,14 @@ paths: - type: string - type: 'null' title: Before - - name: uri + - name: asset_id in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id responses: '200': description: Successful Response @@ -1269,14 +1217,14 @@ paths: - type: string - type: 'null' title: Before - - name: uri + - name: asset_id in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id responses: '204': description: Successful Response @@ -1331,25 +1279,19 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: before - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Before - - name: uri + title: Asset Id + - name: before in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Before responses: '200': description: Successful Response @@ -1401,25 +1343,19 @@ paths: - name: asset_id in: path required: true - schema: - type: integer - title: Asset Id - - name: before - in: query - required: false schema: anyOf: - type: string - type: 'null' - title: Before - - name: uri + title: Asset Id + - name: before in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Before responses: '204': description: Successful Response @@ -2361,14 +2297,14 @@ paths: schema: type: string title: Dag Run Id - - name: uri + - name: asset_id in: query required: false schema: anyOf: - type: string - type: 'null' - title: Uri + title: Asset Id responses: '200': description: Successful Response diff --git a/airflow/api_fastapi/core_api/routes/public/assets.py b/airflow/api_fastapi/core_api/routes/public/assets.py index e0252d1634631..36f4042c753bc 100644 --- a/airflow/api_fastapi/core_api/routes/public/assets.py +++ b/airflow/api_fastapi/core_api/routes/public/assets.py @@ -130,7 +130,6 @@ def get_assets( @assets_router.get( "/assets/aliases", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), - dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_aliases( limit: QueryLimit, @@ -161,7 +160,6 @@ def get_asset_aliases( @assets_router.get( "/assets/aliases/{asset_alias_id}", responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]), - dependencies=[Depends(requires_access_asset(method="GET"))], ) def get_asset_alias(asset_alias_id: int, session: SessionDep): """Get an asset alias.""" diff --git a/airflow/api_fastapi/core_api/security.py b/airflow/api_fastapi/core_api/security.py index 95fc35023c6c8..1ea5fe5967966 100644 --- a/airflow/api_fastapi/core_api/security.py +++ b/airflow/api_fastapi/core_api/security.py @@ -84,12 +84,12 @@ def callback(): def requires_access_asset(method: ResourceMethod) -> Callable: def inner( - uri: str | None = None, + asset_id: str | None = None, user: Annotated[BaseUser | None, Depends(get_user)] = None, ) -> None: def callback(): return get_auth_manager().is_authorized_asset( - method=method, details=AssetDetails(uri=uri), user=user + method=method, details=AssetDetails(id=asset_id), user=user ) _requires_access( diff --git a/airflow/auth/managers/models/resource_details.py b/airflow/auth/managers/models/resource_details.py index 6dec2236bf233..39d4a8a1450c2 100644 --- a/airflow/auth/managers/models/resource_details.py +++ b/airflow/auth/managers/models/resource_details.py @@ -46,7 +46,7 @@ class DagDetails: class AssetDetails: """Represents the details of an asset.""" - uri: str | None = None + id: str | None = None @dataclass diff --git a/airflow/ui/openapi-gen/queries/common.ts b/airflow/ui/openapi-gen/queries/common.ts index a6efb801aad51..4bd97cd7c7408 100644 --- a/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow/ui/openapi-gen/queries/common.ts @@ -58,26 +58,26 @@ export type AssetServiceGetAssetsQueryResult< export const useAssetServiceGetAssetsKey = "AssetServiceGetAssets"; export const UseAssetServiceGetAssetsKeyFn = ( { + assetId, dagIds, limit, namePattern, offset, orderBy, - uri, uriPattern, }: { + assetId?: string; dagIds?: string[]; limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; uriPattern?: string; } = {}, queryKey?: Array, ) => [ useAssetServiceGetAssetsKey, - ...(queryKey ?? [{ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }]), + ...(queryKey ?? [{ assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }]), ]; export type AssetServiceGetAssetAliasesDefaultResponse = Awaited< ReturnType @@ -93,16 +93,14 @@ export const UseAssetServiceGetAssetAliasesKeyFn = ( namePattern, offset, orderBy, - uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; } = {}, queryKey?: Array, -) => [useAssetServiceGetAssetAliasesKey, ...(queryKey ?? [{ limit, namePattern, offset, orderBy, uri }])]; +) => [useAssetServiceGetAssetAliasesKey, ...(queryKey ?? [{ limit, namePattern, offset, orderBy }])]; export type AssetServiceGetAssetAliasDefaultResponse = Awaited>; export type AssetServiceGetAssetAliasQueryResult< TData = AssetServiceGetAssetAliasDefaultResponse, @@ -112,13 +110,11 @@ export const useAssetServiceGetAssetAliasKey = "AssetServiceGetAssetAlias"; export const UseAssetServiceGetAssetAliasKeyFn = ( { assetAliasId, - uri, }: { assetAliasId: number; - uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetAliasKey, ...(queryKey ?? [{ assetAliasId, uri }])]; +) => [useAssetServiceGetAssetAliasKey, ...(queryKey ?? [{ assetAliasId }])]; export type AssetServiceGetAssetEventsDefaultResponse = Awaited< ReturnType >; @@ -139,7 +135,6 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId, timestampGte, timestampLte, - uri, }: { assetId?: number; limit?: number; @@ -151,7 +146,6 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId?: string; timestampGte?: string; timestampLte?: string; - uri?: string; } = {}, queryKey?: Array, ) => [ @@ -168,7 +162,6 @@ export const UseAssetServiceGetAssetEventsKeyFn = ( sourceTaskId, timestampGte, timestampLte, - uri, }, ]), ]; @@ -184,14 +177,12 @@ export const UseAssetServiceGetAssetQueuedEventsKeyFn = ( { assetId, before, - uri, }: { - assetId: number; + assetId: string; before?: string; - uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetQueuedEventsKey, ...(queryKey ?? [{ assetId, before, uri }])]; +) => [useAssetServiceGetAssetQueuedEventsKey, ...(queryKey ?? [{ assetId, before }])]; export type AssetServiceGetAssetDefaultResponse = Awaited>; export type AssetServiceGetAssetQueryResult< TData = AssetServiceGetAssetDefaultResponse, @@ -201,13 +192,11 @@ export const useAssetServiceGetAssetKey = "AssetServiceGetAsset"; export const UseAssetServiceGetAssetKeyFn = ( { assetId, - uri, }: { - assetId: number; - uri?: string; + assetId: string; }, queryKey?: Array, -) => [useAssetServiceGetAssetKey, ...(queryKey ?? [{ assetId, uri }])]; +) => [useAssetServiceGetAssetKey, ...(queryKey ?? [{ assetId }])]; export type AssetServiceGetDagAssetQueuedEventsDefaultResponse = Awaited< ReturnType >; @@ -218,16 +207,16 @@ export type AssetServiceGetDagAssetQueuedEventsQueryResult< export const useAssetServiceGetDagAssetQueuedEventsKey = "AssetServiceGetDagAssetQueuedEvents"; export const UseAssetServiceGetDagAssetQueuedEventsKeyFn = ( { + assetId, before, dagId, - uri, }: { + assetId?: string; before?: string; dagId: string; - uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetDagAssetQueuedEventsKey, ...(queryKey ?? [{ before, dagId, uri }])]; +) => [useAssetServiceGetDagAssetQueuedEventsKey, ...(queryKey ?? [{ assetId, before, dagId }])]; export type AssetServiceGetDagAssetQueuedEventDefaultResponse = Awaited< ReturnType >; @@ -241,15 +230,13 @@ export const UseAssetServiceGetDagAssetQueuedEventKeyFn = ( assetId, before, dagId, - uri, }: { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, queryKey?: Array, -) => [useAssetServiceGetDagAssetQueuedEventKey, ...(queryKey ?? [{ assetId, before, dagId, uri }])]; +) => [useAssetServiceGetDagAssetQueuedEventKey, ...(queryKey ?? [{ assetId, before, dagId }])]; export type ConfigServiceGetConfigsDefaultResponse = Awaited>; export type ConfigServiceGetConfigsQueryResult< TData = ConfigServiceGetConfigsDefaultResponse, @@ -594,16 +581,16 @@ export type DagRunServiceGetUpstreamAssetEventsQueryResult< export const useDagRunServiceGetUpstreamAssetEventsKey = "DagRunServiceGetUpstreamAssetEvents"; export const UseDagRunServiceGetUpstreamAssetEventsKeyFn = ( { + assetId, dagId, dagRunId, - uri, }: { + assetId?: string; dagId: string; dagRunId: string; - uri?: string; }, queryKey?: Array, -) => [useDagRunServiceGetUpstreamAssetEventsKey, ...(queryKey ?? [{ dagId, dagRunId, uri }])]; +) => [useDagRunServiceGetUpstreamAssetEventsKey, ...(queryKey ?? [{ assetId, dagId, dagRunId }])]; export type DagRunServiceGetDagRunsDefaultResponse = Awaited>; export type DagRunServiceGetDagRunsQueryResult< TData = DagRunServiceGetDagRunsDefaultResponse, diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow/ui/openapi-gen/queries/prefetch.ts index 06e7e0f817859..a6950e4748a17 100644 --- a/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow/ui/openapi-gen/queries/prefetch.ts @@ -59,7 +59,7 @@ export const prefetchUseAssetServiceNextRunAssets = ( * Get Assets * Get assets. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.namePattern @@ -72,40 +72,40 @@ export const prefetchUseAssetServiceNextRunAssets = ( export const prefetchUseAssetServiceGetAssets = ( queryClient: QueryClient, { + assetId, dagIds, limit, namePattern, offset, orderBy, - uri, uriPattern, }: { + assetId?: string; dagIds?: string[]; limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; uriPattern?: string; } = {}, ) => queryClient.prefetchQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn({ + assetId, dagIds, limit, namePattern, offset, orderBy, - uri, uriPattern, }), - queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }), + queryFn: () => + AssetService.getAssets({ assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }), }); /** * Get Asset Aliases * Get asset aliases. * @param data The data for the request. - * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -120,25 +120,22 @@ export const prefetchUseAssetServiceGetAssetAliases = ( namePattern, offset, orderBy, - uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; } = {}, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy, uri }), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }), + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }), }); /** * Get Asset Alias * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId - * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -146,25 +143,22 @@ export const prefetchUseAssetServiceGetAssetAlias = ( queryClient: QueryClient, { assetAliasId, - uri, }: { assetAliasId: number; - uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }), - queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }), + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }), + queryFn: () => AssetService.getAssetAlias({ assetAliasId }), }); /** * Get Asset Events * Get asset events. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.orderBy - * @param data.assetId * @param data.sourceDagId * @param data.sourceTaskId * @param data.sourceRunId @@ -187,7 +181,6 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, - uri, }: { assetId?: number; limit?: number; @@ -199,7 +192,6 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId?: string; timestampGte?: string; timestampLte?: string; - uri?: string; } = {}, ) => queryClient.prefetchQuery({ @@ -214,7 +206,6 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, - uri, }), queryFn: () => AssetService.getAssetEvents({ @@ -228,7 +219,6 @@ export const prefetchUseAssetServiceGetAssetEvents = ( sourceTaskId, timestampGte, timestampLte, - uri, }), }); /** @@ -237,7 +227,6 @@ export const prefetchUseAssetServiceGetAssetEvents = ( * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -246,23 +235,20 @@ export const prefetchUseAssetServiceGetAssetQueuedEvents = ( { assetId, before, - uri, }: { - assetId: number; + assetId: string; before?: string; - uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }), + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }), }); /** * Get Asset * Get an asset. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -270,15 +256,13 @@ export const prefetchUseAssetServiceGetAsset = ( queryClient: QueryClient, { assetId, - uri, }: { - assetId: number; - uri?: string; + assetId: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }), - queryFn: () => AssetService.getAsset({ assetId, uri }), + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }), + queryFn: () => AssetService.getAsset({ assetId }), }); /** * Get Dag Asset Queued Events @@ -286,25 +270,25 @@ export const prefetchUseAssetServiceGetAsset = ( * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ export const prefetchUseAssetServiceGetDagAssetQueuedEvents = ( queryClient: QueryClient, { + assetId, before, dagId, - uri, }: { + assetId?: string; before?: string; dagId: string; - uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }), + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ assetId, before, dagId }), + queryFn: () => AssetService.getDagAssetQueuedEvents({ assetId, before, dagId }), }); /** * Get Dag Asset Queued Event @@ -313,7 +297,6 @@ export const prefetchUseAssetServiceGetDagAssetQueuedEvents = ( * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -323,17 +306,15 @@ export const prefetchUseAssetServiceGetDagAssetQueuedEvent = ( assetId, before, dagId, - uri, }: { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }), + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }), }); /** * Get Configs @@ -803,25 +784,25 @@ export const prefetchUseDagRunServiceGetDagRun = ( * @param data The data for the request. * @param data.dagId * @param data.dagRunId - * @param data.uri + * @param data.assetId * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ export const prefetchUseDagRunServiceGetUpstreamAssetEvents = ( queryClient: QueryClient, { + assetId, dagId, dagRunId, - uri, }: { + assetId?: string; dagId: string; dagRunId: string; - uri?: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }), + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ assetId, dagId, dagRunId }), + queryFn: () => DagRunService.getUpstreamAssetEvents({ assetId, dagId, dagRunId }), }); /** * Get Dag Runs diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index c7479e2544516..1bf1033aaf1c1 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -88,7 +88,7 @@ export const useAssetServiceNextRunAssets = < * Get Assets * Get assets. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.namePattern @@ -104,20 +104,20 @@ export const useAssetServiceGetAssets = < TQueryKey extends Array = unknown[], >( { + assetId, dagIds, limit, namePattern, offset, orderBy, - uri, uriPattern, }: { + assetId?: string; dagIds?: string[]; limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; uriPattern?: string; } = {}, queryKey?: TQueryKey, @@ -125,18 +125,17 @@ export const useAssetServiceGetAssets = < ) => useQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn( - { dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }, + { assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }, queryKey, ), queryFn: () => - AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }) as TData, + AssetService.getAssets({ assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }) as TData, ...options, }); /** * Get Asset Aliases * Get asset aliases. * @param data The data for the request. - * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -154,23 +153,18 @@ export const useAssetServiceGetAssetAliases = < namePattern, offset, orderBy, - uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn( - { limit, namePattern, offset, orderBy, uri }, - queryKey, - ), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, ...options, }); /** @@ -178,7 +172,6 @@ export const useAssetServiceGetAssetAliases = < * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId - * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -189,28 +182,25 @@ export const useAssetServiceGetAssetAlias = < >( { assetAliasId, - uri, }: { assetAliasId: number; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }, queryKey), - queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }, queryKey), + queryFn: () => AssetService.getAssetAlias({ assetAliasId }) as TData, ...options, }); /** * Get Asset Events * Get asset events. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.orderBy - * @param data.assetId * @param data.sourceDagId * @param data.sourceTaskId * @param data.sourceRunId @@ -236,7 +226,6 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, - uri, }: { assetId?: number; limit?: number; @@ -248,7 +237,6 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId?: string; timestampGte?: string; timestampLte?: string; - uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, @@ -266,7 +254,6 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, - uri, }, queryKey, ), @@ -282,7 +269,6 @@ export const useAssetServiceGetAssetEvents = < sourceTaskId, timestampGte, timestampLte, - uri, }) as TData, ...options, }); @@ -292,7 +278,6 @@ export const useAssetServiceGetAssetEvents = < * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -304,18 +289,16 @@ export const useAssetServiceGetAssetQueuedEvents = < { assetId, before, - uri, }: { - assetId: number; + assetId: string; before?: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }, queryKey), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }, queryKey), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }) as TData, ...options, }); /** @@ -323,7 +306,6 @@ export const useAssetServiceGetAssetQueuedEvents = < * Get an asset. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -334,17 +316,15 @@ export const useAssetServiceGetAsset = < >( { assetId, - uri, }: { - assetId: number; - uri?: string; + assetId: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }, queryKey), - queryFn: () => AssetService.getAsset({ assetId, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }, queryKey), + queryFn: () => AssetService.getAsset({ assetId }) as TData, ...options, }); /** @@ -353,7 +333,7 @@ export const useAssetServiceGetAsset = < * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -363,20 +343,20 @@ export const useAssetServiceGetDagAssetQueuedEvents = < TQueryKey extends Array = unknown[], >( { + assetId, before, dagId, - uri, }: { + assetId?: string; before?: string; dagId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ assetId, before, dagId }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvents({ assetId, before, dagId }) as TData, ...options, }); /** @@ -386,7 +366,6 @@ export const useAssetServiceGetDagAssetQueuedEvents = < * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -399,19 +378,17 @@ export const useAssetServiceGetDagAssetQueuedEvent = < assetId, before, dagId, - uri, }: { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }) as TData, ...options, }); /** @@ -973,7 +950,7 @@ export const useDagRunServiceGetDagRun = < * @param data The data for the request. * @param data.dagId * @param data.dagRunId - * @param data.uri + * @param data.assetId * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -983,20 +960,20 @@ export const useDagRunServiceGetUpstreamAssetEvents = < TQueryKey extends Array = unknown[], >( { + assetId, dagId, dagRunId, - uri, }: { + assetId?: string; dagId: string; dagRunId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }, queryKey), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }) as TData, + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ assetId, dagId, dagRunId }, queryKey), + queryFn: () => DagRunService.getUpstreamAssetEvents({ assetId, dagId, dagRunId }) as TData, ...options, }); /** @@ -2917,7 +2894,7 @@ export const useLoginServiceLogin = < * Create asset events. * @param data The data for the request. * @param data.requestBody - * @param data.uri + * @param data.assetId * @returns AssetEventResponse Successful Response * @throws ApiError */ @@ -2931,8 +2908,8 @@ export const useAssetServiceCreateAssetEvent = < TData, TError, { + assetId?: string; requestBody: CreateAssetEventsBody; - uri?: string; }, TContext >, @@ -2943,13 +2920,13 @@ export const useAssetServiceCreateAssetEvent = < TData, TError, { + assetId?: string; requestBody: CreateAssetEventsBody; - uri?: string; }, TContext >({ - mutationFn: ({ requestBody, uri }) => - AssetService.createAssetEvent({ requestBody, uri }) as unknown as Promise, + mutationFn: ({ assetId, requestBody }) => + AssetService.createAssetEvent({ assetId, requestBody }) as unknown as Promise, ...options, }); /** @@ -2957,7 +2934,6 @@ export const useAssetServiceCreateAssetEvent = < * Materialize an asset by triggering a DAG run that produces it. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns DAGRunResponse Successful Response * @throws ApiError */ @@ -2971,8 +2947,7 @@ export const useAssetServiceMaterializeAsset = < TData, TError, { - assetId: number; - uri?: string; + assetId: string; }, TContext >, @@ -2983,13 +2958,11 @@ export const useAssetServiceMaterializeAsset = < TData, TError, { - assetId: number; - uri?: string; + assetId: string; }, TContext >({ - mutationFn: ({ assetId, uri }) => - AssetService.materializeAsset({ assetId, uri }) as unknown as Promise, + mutationFn: ({ assetId }) => AssetService.materializeAsset({ assetId }) as unknown as Promise, ...options, }); /** @@ -4352,7 +4325,6 @@ export const useVariableServiceBulkVariables = < * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @param data.dagId * @returns void Successful Response * @throws ApiError @@ -4367,10 +4339,9 @@ export const useAssetServiceDeleteAssetQueuedEvents = < TData, TError, { - assetId: number; + assetId: string; before?: string; dagId?: string; - uri?: string; }, TContext >, @@ -4381,15 +4352,14 @@ export const useAssetServiceDeleteAssetQueuedEvents = < TData, TError, { - assetId: number; + assetId: string; before?: string; dagId?: string; - uri?: string; }, TContext >({ - mutationFn: ({ assetId, before, dagId, uri }) => - AssetService.deleteAssetQueuedEvents({ assetId, before, dagId, uri }) as unknown as Promise, + mutationFn: ({ assetId, before, dagId }) => + AssetService.deleteAssetQueuedEvents({ assetId, before, dagId }) as unknown as Promise, ...options, }); /** @@ -4397,7 +4367,7 @@ export const useAssetServiceDeleteAssetQueuedEvents = < * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns void Successful Response * @throws ApiError */ @@ -4411,9 +4381,9 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < TData, TError, { + assetId?: string; before?: string; dagId: string; - uri?: string; }, TContext >, @@ -4424,14 +4394,14 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < TData, TError, { + assetId?: string; before?: string; dagId: string; - uri?: string; }, TContext >({ - mutationFn: ({ before, dagId, uri }) => - AssetService.deleteDagAssetQueuedEvents({ before, dagId, uri }) as unknown as Promise, + mutationFn: ({ assetId, before, dagId }) => + AssetService.deleteDagAssetQueuedEvents({ assetId, before, dagId }) as unknown as Promise, ...options, }); /** @@ -4441,7 +4411,6 @@ export const useAssetServiceDeleteDagAssetQueuedEvents = < * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -4455,10 +4424,9 @@ export const useAssetServiceDeleteDagAssetQueuedEvent = < TData, TError, { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, TContext >, @@ -4469,15 +4437,14 @@ export const useAssetServiceDeleteDagAssetQueuedEvent = < TData, TError, { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, TContext >({ - mutationFn: ({ assetId, before, dagId, uri }) => - AssetService.deleteDagAssetQueuedEvent({ assetId, before, dagId, uri }) as unknown as Promise, + mutationFn: ({ assetId, before, dagId }) => + AssetService.deleteDagAssetQueuedEvent({ assetId, before, dagId }) as unknown as Promise, ...options, }); /** diff --git a/airflow/ui/openapi-gen/queries/suspense.ts b/airflow/ui/openapi-gen/queries/suspense.ts index b4e2fca28ab07..67564a9afd60e 100644 --- a/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow/ui/openapi-gen/queries/suspense.ts @@ -65,7 +65,7 @@ export const useAssetServiceNextRunAssetsSuspense = < * Get Assets * Get assets. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.namePattern @@ -81,20 +81,20 @@ export const useAssetServiceGetAssetsSuspense = < TQueryKey extends Array = unknown[], >( { + assetId, dagIds, limit, namePattern, offset, orderBy, - uri, uriPattern, }: { + assetId?: string; dagIds?: string[]; limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; uriPattern?: string; } = {}, queryKey?: TQueryKey, @@ -102,18 +102,17 @@ export const useAssetServiceGetAssetsSuspense = < ) => useSuspenseQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn( - { dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }, + { assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }, queryKey, ), queryFn: () => - AssetService.getAssets({ dagIds, limit, namePattern, offset, orderBy, uri, uriPattern }) as TData, + AssetService.getAssets({ assetId, dagIds, limit, namePattern, offset, orderBy, uriPattern }) as TData, ...options, }); /** * Get Asset Aliases * Get asset aliases. * @param data The data for the request. - * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -131,23 +130,18 @@ export const useAssetServiceGetAssetAliasesSuspense = < namePattern, offset, orderBy, - uri, }: { limit?: number; namePattern?: string; offset?: number; orderBy?: string; - uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn( - { limit, namePattern, offset, orderBy, uri }, - queryKey, - ), - queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), + queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, ...options, }); /** @@ -155,7 +149,6 @@ export const useAssetServiceGetAssetAliasesSuspense = < * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId - * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -166,28 +159,25 @@ export const useAssetServiceGetAssetAliasSuspense = < >( { assetAliasId, - uri, }: { assetAliasId: number; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId, uri }, queryKey), - queryFn: () => AssetService.getAssetAlias({ assetAliasId, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetAliasKeyFn({ assetAliasId }, queryKey), + queryFn: () => AssetService.getAssetAlias({ assetAliasId }) as TData, ...options, }); /** * Get Asset Events * Get asset events. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.orderBy - * @param data.assetId * @param data.sourceDagId * @param data.sourceTaskId * @param data.sourceRunId @@ -213,7 +203,6 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, - uri, }: { assetId?: number; limit?: number; @@ -225,7 +214,6 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId?: string; timestampGte?: string; timestampLte?: string; - uri?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, @@ -243,7 +231,6 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, - uri, }, queryKey, ), @@ -259,7 +246,6 @@ export const useAssetServiceGetAssetEventsSuspense = < sourceTaskId, timestampGte, timestampLte, - uri, }) as TData, ...options, }); @@ -269,7 +255,6 @@ export const useAssetServiceGetAssetEventsSuspense = < * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -281,18 +266,16 @@ export const useAssetServiceGetAssetQueuedEventsSuspense = < { assetId, before, - uri, }: { - assetId: number; + assetId: string; before?: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before, uri }, queryKey), - queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetQueuedEventsKeyFn({ assetId, before }, queryKey), + queryFn: () => AssetService.getAssetQueuedEvents({ assetId, before }) as TData, ...options, }); /** @@ -300,7 +283,6 @@ export const useAssetServiceGetAssetQueuedEventsSuspense = < * Get an asset. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -311,17 +293,15 @@ export const useAssetServiceGetAssetSuspense = < >( { assetId, - uri, }: { - assetId: number; - uri?: string; + assetId: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId, uri }, queryKey), - queryFn: () => AssetService.getAsset({ assetId, uri }) as TData, + queryKey: Common.UseAssetServiceGetAssetKeyFn({ assetId }, queryKey), + queryFn: () => AssetService.getAsset({ assetId }) as TData, ...options, }); /** @@ -330,7 +310,7 @@ export const useAssetServiceGetAssetSuspense = < * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -340,20 +320,20 @@ export const useAssetServiceGetDagAssetQueuedEventsSuspense = < TQueryKey extends Array = unknown[], >( { + assetId, before, dagId, - uri, }: { + assetId?: string; before?: string; dagId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ before, dagId, uri }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvents({ before, dagId, uri }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventsKeyFn({ assetId, before, dagId }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvents({ assetId, before, dagId }) as TData, ...options, }); /** @@ -363,7 +343,6 @@ export const useAssetServiceGetDagAssetQueuedEventsSuspense = < * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -376,19 +355,17 @@ export const useAssetServiceGetDagAssetQueuedEventSuspense = < assetId, before, dagId, - uri, }: { - assetId: number; + assetId: string; before?: string; dagId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId, uri }, queryKey), - queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId, uri }) as TData, + queryKey: Common.UseAssetServiceGetDagAssetQueuedEventKeyFn({ assetId, before, dagId }, queryKey), + queryFn: () => AssetService.getDagAssetQueuedEvent({ assetId, before, dagId }) as TData, ...options, }); /** @@ -950,7 +927,7 @@ export const useDagRunServiceGetDagRunSuspense = < * @param data The data for the request. * @param data.dagId * @param data.dagRunId - * @param data.uri + * @param data.assetId * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -960,20 +937,20 @@ export const useDagRunServiceGetUpstreamAssetEventsSuspense = < TQueryKey extends Array = unknown[], >( { + assetId, dagId, dagRunId, - uri, }: { + assetId?: string; dagId: string; dagRunId: string; - uri?: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ dagId, dagRunId, uri }, queryKey), - queryFn: () => DagRunService.getUpstreamAssetEvents({ dagId, dagRunId, uri }) as TData, + queryKey: Common.UseDagRunServiceGetUpstreamAssetEventsKeyFn({ assetId, dagId, dagRunId }, queryKey), + queryFn: () => DagRunService.getUpstreamAssetEvents({ assetId, dagId, dagRunId }) as TData, ...options, }); /** diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index 3531bea7870ad..13f309a40a728 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -236,7 +236,7 @@ export class AssetService { * Get Assets * Get assets. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.namePattern @@ -251,7 +251,7 @@ export class AssetService { method: "GET", url: "/public/assets", query: { - uri: data.uri, + asset_id: data.assetId, limit: data.limit, offset: data.offset, name_pattern: data.namePattern, @@ -272,7 +272,6 @@ export class AssetService { * Get Asset Aliases * Get asset aliases. * @param data The data for the request. - * @param data.uri * @param data.limit * @param data.offset * @param data.namePattern @@ -285,7 +284,6 @@ export class AssetService { method: "GET", url: "/public/assets/aliases", query: { - uri: data.uri, limit: data.limit, offset: data.offset, name_pattern: data.namePattern, @@ -305,7 +303,6 @@ export class AssetService { * Get an asset alias. * @param data The data for the request. * @param data.assetAliasId - * @param data.uri * @returns unknown Successful Response * @throws ApiError */ @@ -316,9 +313,6 @@ export class AssetService { path: { asset_alias_id: data.assetAliasId, }, - query: { - uri: data.uri, - }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -332,11 +326,10 @@ export class AssetService { * Get Asset Events * Get asset events. * @param data The data for the request. - * @param data.uri + * @param data.assetId * @param data.limit * @param data.offset * @param data.orderBy - * @param data.assetId * @param data.sourceDagId * @param data.sourceTaskId * @param data.sourceRunId @@ -351,11 +344,10 @@ export class AssetService { method: "GET", url: "/public/assets/events", query: { - uri: data.uri, + asset_id: data.assetId, limit: data.limit, offset: data.offset, order_by: data.orderBy, - asset_id: data.assetId, source_dag_id: data.sourceDagId, source_task_id: data.sourceTaskId, source_run_id: data.sourceRunId, @@ -377,7 +369,7 @@ export class AssetService { * Create asset events. * @param data The data for the request. * @param data.requestBody - * @param data.uri + * @param data.assetId * @returns AssetEventResponse Successful Response * @throws ApiError */ @@ -386,7 +378,7 @@ export class AssetService { method: "POST", url: "/public/assets/events", query: { - uri: data.uri, + asset_id: data.assetId, }, body: data.requestBody, mediaType: "application/json", @@ -404,7 +396,6 @@ export class AssetService { * Materialize an asset by triggering a DAG run that produces it. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns DAGRunResponse Successful Response * @throws ApiError */ @@ -415,9 +406,6 @@ export class AssetService { path: { asset_id: data.assetId, }, - query: { - uri: data.uri, - }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -434,7 +422,6 @@ export class AssetService { * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -449,7 +436,6 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, }, errors: { 401: "Unauthorized", @@ -466,7 +452,6 @@ export class AssetService { * @param data The data for the request. * @param data.assetId * @param data.before - * @param data.uri * @param data.dagId * @returns void Successful Response * @throws ApiError @@ -482,7 +467,6 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, dag_id: data.dagId, }, errors: { @@ -499,7 +483,6 @@ export class AssetService { * Get an asset. * @param data The data for the request. * @param data.assetId - * @param data.uri * @returns AssetResponse Successful Response * @throws ApiError */ @@ -510,9 +493,6 @@ export class AssetService { path: { asset_id: data.assetId, }, - query: { - uri: data.uri, - }, errors: { 401: "Unauthorized", 403: "Forbidden", @@ -528,7 +508,7 @@ export class AssetService { * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns QueuedEventCollectionResponse Successful Response * @throws ApiError */ @@ -543,7 +523,7 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, + asset_id: data.assetId, }, errors: { 401: "Unauthorized", @@ -559,7 +539,7 @@ export class AssetService { * @param data The data for the request. * @param data.dagId * @param data.before - * @param data.uri + * @param data.assetId * @returns void Successful Response * @throws ApiError */ @@ -574,7 +554,7 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, + asset_id: data.assetId, }, errors: { 400: "Bad Request", @@ -593,7 +573,6 @@ export class AssetService { * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns QueuedEventResponse Successful Response * @throws ApiError */ @@ -609,7 +588,6 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, }, errors: { 401: "Unauthorized", @@ -627,7 +605,6 @@ export class AssetService { * @param data.dagId * @param data.assetId * @param data.before - * @param data.uri * @returns void Successful Response * @throws ApiError */ @@ -643,7 +620,6 @@ export class AssetService { }, query: { before: data.before, - uri: data.uri, }, errors: { 400: "Bad Request", @@ -1405,7 +1381,7 @@ export class DagRunService { * @param data The data for the request. * @param data.dagId * @param data.dagRunId - * @param data.uri + * @param data.assetId * @returns AssetEventCollectionResponse Successful Response * @throws ApiError */ @@ -1420,7 +1396,7 @@ export class DagRunService { dag_run_id: data.dagRunId, }, query: { - uri: data.uri, + asset_id: data.assetId, }, errors: { 401: "Unauthorized", diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index 820eefe724885..df4a3c6e32182 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -1616,12 +1616,12 @@ export type NextRunAssetsResponse = { }; export type GetAssetsData = { + assetId?: string | null; dagIds?: Array; limit?: number; namePattern?: string | null; offset?: number; orderBy?: string; - uri?: string | null; uriPattern?: string | null; }; @@ -1632,14 +1632,12 @@ export type GetAssetAliasesData = { namePattern?: string | null; offset?: number; orderBy?: string; - uri?: string | null; }; export type GetAssetAliasesResponse = AssetAliasCollectionResponse; export type GetAssetAliasData = { assetAliasId: number; - uri?: string | null; }; export type GetAssetAliasResponse = unknown; @@ -1655,79 +1653,72 @@ export type GetAssetEventsData = { sourceTaskId?: string | null; timestampGte?: string | null; timestampLte?: string | null; - uri?: string | null; }; export type GetAssetEventsResponse = AssetEventCollectionResponse; export type CreateAssetEventData = { + assetId?: string | null; requestBody: CreateAssetEventsBody; - uri?: string | null; }; export type CreateAssetEventResponse = AssetEventResponse; export type MaterializeAssetData = { - assetId: number; - uri?: string | null; + assetId: string | null; }; export type MaterializeAssetResponse = DAGRunResponse; export type GetAssetQueuedEventsData = { - assetId: number; + assetId: string | null; before?: string | null; - uri?: string | null; }; export type GetAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteAssetQueuedEventsData = { - assetId: number; + assetId: string | null; before?: string | null; dagId?: string | null; - uri?: string | null; }; export type DeleteAssetQueuedEventsResponse = void; export type GetAssetData = { - assetId: number; - uri?: string | null; + assetId: string | null; }; export type GetAssetResponse = AssetResponse; export type GetDagAssetQueuedEventsData = { + assetId?: string | null; before?: string | null; dagId: string | null; - uri?: string | null; }; export type GetDagAssetQueuedEventsResponse = QueuedEventCollectionResponse; export type DeleteDagAssetQueuedEventsData = { + assetId?: string | null; before?: string | null; dagId: string | null; - uri?: string | null; }; export type DeleteDagAssetQueuedEventsResponse = void; export type GetDagAssetQueuedEventData = { - assetId: number; + assetId: string | null; before?: string | null; dagId: string | null; - uri?: string | null; }; export type GetDagAssetQueuedEventResponse = QueuedEventResponse; export type DeleteDagAssetQueuedEventData = { - assetId: number; + assetId: string | null; before?: string | null; dagId: string | null; - uri?: string | null; }; export type DeleteDagAssetQueuedEventResponse = void; @@ -1935,9 +1926,9 @@ export type PatchDagRunData = { export type PatchDagRunResponse = DAGRunResponse; export type GetUpstreamAssetEventsData = { + assetId?: string | null; dagId: string; dagRunId: string; - uri?: string | null; }; export type GetUpstreamAssetEventsResponse = AssetEventCollectionResponse; diff --git a/providers/amazon/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py b/providers/amazon/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py index 455d03fba4725..7cb08f7c0c1f0 100644 --- a/providers/amazon/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py +++ b/providers/amazon/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py @@ -162,9 +162,9 @@ def is_authorized_dag( def is_authorized_asset( self, *, method: ResourceMethod, user: AwsAuthManagerUser, details: AssetDetails | None = None ) -> bool: - asset_uri = details.uri if details else None + asset_id = details.id if details else None return self.avp_facade.is_authorized( - method=method, entity_type=AvpEntities.ASSET, user=user, entity_id=asset_uri + method=method, entity_type=AvpEntities.ASSET, user=user, entity_id=asset_id ) def is_authorized_pool( diff --git a/providers/amazon/tests/unit/amazon/aws/auth_manager/test_aws_auth_manager.py b/providers/amazon/tests/unit/amazon/aws/auth_manager/test_aws_auth_manager.py index a69fe496e1f2d..5d84ee2a60384 100644 --- a/providers/amazon/tests/unit/amazon/aws/auth_manager/test_aws_auth_manager.py +++ b/providers/amazon/tests/unit/amazon/aws/auth_manager/test_aws_auth_manager.py @@ -221,7 +221,7 @@ def test_is_authorized_dag( "details, user, expected_user, expected_entity_id", [ (None, mock, ANY, None), - (AssetDetails(uri="uri"), mock, mock, "uri"), + (AssetDetails(id="1"), mock, mock, "1"), ], ) @patch.object(AwsAuthManager, "avp_facade") From 2cf9699ac2b3d85d6a0fc384e470430f26d4b64b Mon Sep 17 00:00:00 2001 From: kalyanr Date: Sat, 1 Mar 2025 17:01:39 +0530 Subject: [PATCH 15/19] remove asset alias tests --- .../core_api/routes/public/test_assets.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tests/api_fastapi/core_api/routes/public/test_assets.py b/tests/api_fastapi/core_api/routes/public/test_assets.py index 86bd397595498..8ac1c08cbc32c 100644 --- a/tests/api_fastapi/core_api/routes/public/test_assets.py +++ b/tests/api_fastapi/core_api/routes/public/test_assets.py @@ -470,14 +470,6 @@ def test_should_respond_200(self, test_client, session): "total_entries": 2, } - def test_should_respond_401(self, unauthenticated_test_client): - response = unauthenticated_test_client.get("/public/assets/aliases") - assert response.status_code == 401 - - def test_should_respond_403(self, unauthorized_test_client): - response = unauthorized_test_client.get("/public/assets/aliases") - assert response.status_code == 403 - def test_order_by_raises_400_for_invalid_attr(self, test_client, session): response = test_client.get("/public/assets/aliases?order_by=fake") @@ -855,14 +847,6 @@ def test_should_respond_200(self, test_client, session): assert response.status_code == 200 assert response.json() == {"id": 1, "name": "simple1", "group": "alias"} - def test_should_respond_401(self, unauthenticated_test_client): - response = unauthenticated_test_client.get("/public/assets/aliases/1") - assert response.status_code == 401 - - def test_should_respond_403(self, unauthorized_test_client): - response = unauthorized_test_client.get("/public/assets/1") - assert response.status_code == 403 - def test_should_respond_404(self, test_client): response = test_client.get("/public/assets/aliases/1") assert response.status_code == 404 From 83bce1751b0406d1f1e537723c29c9b7e4f95eec Mon Sep 17 00:00:00 2001 From: kalyanr Date: Sat, 1 Mar 2025 17:11:05 +0530 Subject: [PATCH 16/19] remove unused session --- tests/api_fastapi/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api_fastapi/conftest.py b/tests/api_fastapi/conftest.py index cfe7e1f7d5cf4..02d961d1291e4 100644 --- a/tests/api_fastapi/conftest.py +++ b/tests/api_fastapi/conftest.py @@ -119,7 +119,7 @@ def configure_git_connection_for_dag_bundle(session): @pytest.fixture -def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_bundle, session): +def make_dag_with_multiple_versions(dag_maker, configure_git_connection_for_dag_bundle): """ Create DAG with multiple versions From f0fc5acc4ec1e1427d7f77e6aa0684c3b4a4f66c Mon Sep 17 00:00:00 2001 From: kalyanr Date: Mon, 3 Mar 2025 21:58:51 +0530 Subject: [PATCH 17/19] add newsfragment --- newsfragments/42360.significant.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 newsfragments/42360.significant.rst diff --git a/newsfragments/42360.significant.rst b/newsfragments/42360.significant.rst new file mode 100644 index 0000000000000..d881cd789fa99 --- /dev/null +++ b/newsfragments/42360.significant.rst @@ -0,0 +1,13 @@ +``uri`` is replaced with ``id`` in ``AssetDetails`` . Hence, ``is_authorized_asset`` method needs to be updated in Auth Managers to use ``id`` instead of ``uri``. + + +* Types of change + + * [ ] Dag changes + * [ ] Config changes + * [ ] API changes + * [ ] CLI changes + * [ ] Behaviour changes + * [ ] Plugin changes + * [ ] Dependency changes + * [X] Code interface changes From de5ab58bd90a8e3c9a00e9cb14df99c0c8047409 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Wed, 5 Mar 2025 09:29:41 +0530 Subject: [PATCH 18/19] rename newsfragment --- newsfragments/{42360.significant.rst => 47136.significant.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename newsfragments/{42360.significant.rst => 47136.significant.rst} (100%) diff --git a/newsfragments/42360.significant.rst b/newsfragments/47136.significant.rst similarity index 100% rename from newsfragments/42360.significant.rst rename to newsfragments/47136.significant.rst From 8835427f7487aa0a3603c36faa33791281a3afc2 Mon Sep 17 00:00:00 2001 From: kalyanr Date: Wed, 5 Mar 2025 10:59:05 +0530 Subject: [PATCH 19/19] use lambda --- airflow/api_fastapi/core_api/security.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/airflow/api_fastapi/core_api/security.py b/airflow/api_fastapi/core_api/security.py index 27b778dfe16f1..0c9be4be64667 100644 --- a/airflow/api_fastapi/core_api/security.py +++ b/airflow/api_fastapi/core_api/security.py @@ -146,13 +146,10 @@ def inner( ) -> None: asset_id = request.path_params.get("asset_id") - def callback(): - return get_auth_manager().is_authorized_asset( - method=method, details=AssetDetails(id=asset_id), user=user - ) - _requires_access( - is_authorized_callback=callback, + is_authorized_callback=lambda: get_auth_manager().is_authorized_asset( + method=method, details=AssetDetails(id=asset_id), user=user + ), ) return inner