diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py index 2a6bd6bec8af2..f2ac1f7a9403a 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py @@ -17,15 +17,12 @@ from __future__ import annotations -import json from collections import abc from typing import Annotated -from pydantic import Field, field_validator -from pydantic_core.core_schema import ValidationInfo +from pydantic import Field from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel -from airflow.sdk.execution_time.secrets_masker import redact # Response Models @@ -42,26 +39,6 @@ class ConnectionResponse(BaseModel): password: str | None extra: str | None - @field_validator("password", mode="after") - @classmethod - def redact_password(cls, v: str | None, field_info: ValidationInfo) -> str | None: - if v is None: - return None - return str(redact(v, field_info.field_name)) - - @field_validator("extra", mode="before") - @classmethod - def redact_extra(cls, v: str | None) -> str | None: - if v is None: - return None - try: - extra_dict = json.loads(v) - redacted_dict = redact(extra_dict) - return json.dumps(redacted_dict) - except json.JSONDecodeError: - # we can't redact fields in an unstructured `extra` - return v - class ConnectionCollectionResponse(BaseModel): """Connection Collection serializer for responses.""" diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx index bf921a1de3c99..9e4e38647eaf4 100644 --- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx @@ -57,7 +57,7 @@ const ConnectionForm = ({ const { conf: extra, setConf } = useParamStore(); const { control, - formState: { isValid }, + formState: { isDirty, isValid }, handleSubmit, reset, watch, @@ -94,6 +94,14 @@ const ConnectionForm = ({ mutateConnection(data); }; + const hasChanges = () => { + if (isDirty) { + return true; + } + + return JSON.stringify(JSON.parse(extra)) !== JSON.stringify(JSON.parse(initialConnection.extra)); + }; + const validateAndPrettifyJson = (value: string) => { try { const parsedJson = JSON.parse(value) as JSON; @@ -234,7 +242,7 @@ const ConnectionForm = ({