This is an automated email from the ASF dual-hosted git repository.

pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2f5fb76d467 Add `get_display_name` to `BaseUser` interface  (#70583)
2f5fb76d467 is described below

commit 2f5fb76d467b8cb84b4ebdd11058df7060fb41cc
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Jul 28 14:02:43 2026 +0200

    Add `get_display_name` to `BaseUser` interface  (#70583)
    
    * Show user display name in the audit log via get_display_name
    
    The audit log's owner_display_name always equalled owner because the action
    logger stored get_name() in both fields. Add a get_display_name() to the 
auth
    manager user model, defaulting to get_name() so auth managers written 
before it
    keep working unchanged, and have the FAB user return its full name. The 
action
    logger now records get_display_name() as owner_display_name, so the audit 
log
    can show a friendlier name than the raw owner identifier where one exists.
    
    Follow-up to #68833.
    
    * Add an owner display name filter to the audit log
    
    The audit log user column now shows owner_display_name, so its filter should
    match that value. Add server-side pattern and prefix-pattern search params 
on
    owner_display_name and point the existing User filter at them, and drop the
    redundant UI owner fallback so the displayed value and the filter stay in 
sync.
    
    * Use spec on the mocked request and session in the decorator test
    
    * Use a real request instead of a mock in the decorator test
    
    A real Request built from a minimal ASGI scope supplies genuine empty
    headers/query/path params, so nothing needs stubbing and the test cannot 
drift
    from the real request interface. The session stays a spec'd mock to capture 
the
    logged row.
---
 .../api_fastapi/auth/managers/models/base_user.py  |  9 +++++++
 .../core_api/openapi/v2-rest-api-generated.yaml    | 26 ++++++++++++++++++
 .../core_api/routes/public/event_logs.py           | 10 +++++++
 .../src/airflow/api_fastapi/logging/decorators.py  |  2 +-
 .../src/airflow/ui/openapi-gen/queries/common.ts   |  6 +++--
 .../ui/openapi-gen/queries/ensureQueryData.ts      |  8 ++++--
 .../src/airflow/ui/openapi-gen/queries/prefetch.ts |  8 ++++--
 .../src/airflow/ui/openapi-gen/queries/queries.ts  |  8 ++++--
 .../src/airflow/ui/openapi-gen/queries/suspense.ts |  8 ++++--
 .../ui/openapi-gen/requests/services.gen.ts        |  4 +++
 .../airflow/ui/openapi-gen/requests/types.gen.ts   |  8 ++++++
 .../src/airflow/ui/src/pages/Events/Events.tsx     |  6 ++---
 .../api_fastapi/auth/managers/models/__init__.py}  | 14 ----------
 .../auth/managers/models/test_base_user.py}        | 19 +++++++------
 .../core_api/routes/public/test_event_logs.py      | 14 ++++++++++
 .../unit/api_fastapi/logging/test_decorators.py    | 31 ++++++++++++++++++++++
 .../providers/fab/auth_manager/models/__init__.py  |  3 +++
 .../fab/auth_manager/models/test_user_model.py     |  7 +++++
 18 files changed, 155 insertions(+), 36 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py 
b/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
index 7f060f3121e..c94ee0c1d8d 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
+++ b/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
@@ -28,3 +28,12 @@ class BaseUser:
 
     @abstractmethod
     def get_name(self) -> str: ...
+
+    def get_display_name(self) -> str:
+        """
+        Return a human-friendly display name for the user.
+
+        Not abstract for backward compatibility reasons: auth managers written
+        before this method existed keep working without any change.
+        """
+        return self.get_name()
diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
 
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
index d5807bfec27..fea2773828c 100644
--- 
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
+++ 
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
@@ -4644,6 +4644,20 @@ paths:
         description: "Case-insensitive substring match (SQL `ILIKE`). Slower 
than\
           \ `owner_prefix_pattern` on large tables \u2014 see \"Filtering with 
pattern\
           \ parameters\"."
+      - name: owner_display_name_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          description: "Case-insensitive substring match (SQL `ILIKE`). Slower 
than\
+            \ `owner_display_name_prefix_pattern` on large tables \u2014 see 
\"Filtering\
+            \ with pattern parameters\"."
+          title: Owner Display Name Pattern
+        description: "Case-insensitive substring match (SQL `ILIKE`). Slower 
than\
+          \ `owner_display_name_prefix_pattern` on large tables \u2014 see 
\"Filtering\
+          \ with pattern parameters\"."
       - name: event_pattern
         in: query
         required: false
@@ -4706,6 +4720,18 @@ paths:
           title: Owner Prefix Pattern
         description: Case-sensitive, index-friendly prefix match. See 
"Filtering with
           pattern parameters".
+      - name: owner_display_name_prefix_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          description: Case-sensitive, index-friendly prefix match. See 
"Filtering
+            with pattern parameters".
+          title: Owner Display Name Prefix Pattern
+        description: Case-sensitive, index-friendly prefix match. See 
"Filtering with
+          pattern parameters".
       - name: event_prefix_pattern
         in: query
         required: false
diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/event_logs.py 
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/event_logs.py
index 881f9f5db1a..eb0c4009814 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/event_logs.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/event_logs.py
@@ -141,6 +141,10 @@ def get_event_logs(
     task_id_pattern: Annotated[_SearchParam, 
Depends(search_param_factory(Log.task_id, "task_id_pattern"))],
     run_id_pattern: Annotated[_SearchParam, 
Depends(search_param_factory(Log.run_id, "run_id_pattern"))],
     owner_pattern: Annotated[_SearchParam, 
Depends(search_param_factory(Log.owner, "owner_pattern"))],
+    owner_display_name_pattern: Annotated[
+        _SearchParam,
+        Depends(search_param_factory(Log.owner_display_name, 
"owner_display_name_pattern")),
+    ],
     event_pattern: Annotated[_SearchParam, 
Depends(search_param_factory(Log.event, "event_pattern"))],
     # Prefix pattern search filters (index-friendly, case-sensitive)
     dag_id_prefix_pattern: Annotated[
@@ -159,6 +163,10 @@ def get_event_logs(
         _PrefixSearchParam,
         Depends(prefix_search_param_factory(Log.owner, 
"owner_prefix_pattern")),
     ],
+    owner_display_name_prefix_pattern: Annotated[
+        _PrefixSearchParam,
+        Depends(prefix_search_param_factory(Log.owner_display_name, 
"owner_display_name_prefix_pattern")),
+    ],
     event_prefix_pattern: Annotated[
         _PrefixSearchParam,
         Depends(prefix_search_param_factory(Log.event, 
"event_prefix_pattern")),
@@ -202,6 +210,8 @@ def get_event_logs(
             run_id_prefix_pattern,
             owner_pattern,
             owner_prefix_pattern,
+            owner_display_name_pattern,
+            owner_display_name_prefix_pattern,
             event_pattern,
             event_prefix_pattern,
             # Permission
diff --git a/airflow-core/src/airflow/api_fastapi/logging/decorators.py 
b/airflow-core/src/airflow/api_fastapi/logging/decorators.py
index f32a2bffc70..7c32c70a5ca 100644
--- a/airflow-core/src/airflow/api_fastapi/logging/decorators.py
+++ b/airflow-core/src/airflow/api_fastapi/logging/decorators.py
@@ -98,7 +98,7 @@ def action_logging(event: str | None = None):
             user_display = ""
         else:
             user_name = user.get_name()
-            user_display = user.get_name()
+            user_display = user.get_display_name()
 
         has_json_body = "application/json" in 
request.headers.get("content-type", "") and await request.body()
         request_body = {}
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts 
b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
index 05a4b47ec1b..2761037fcc2 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -389,7 +389,7 @@ export const UseEventLogServiceGetEventLogKeyFn = ({ 
eventLogId }: {
 export type EventLogServiceGetEventLogsDefaultResponse = 
Awaited<ReturnType<typeof EventLogService.getEventLogs>>;
 export type EventLogServiceGetEventLogsQueryResult<TData = 
EventLogServiceGetEventLogsDefaultResponse, TError = unknown> = 
UseQueryResult<TData, TError>;
 export const useEventLogServiceGetEventLogsKey = "EventLogServiceGetEventLogs";
-export const UseEventLogServiceGetEventLogsKeyFn = ({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerPattern, ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, 
taskId, taskIdPattern, taskIdPrefixPattern, tryNumber }: {
+export const UseEventLogServiceGetEventLogsKeyFn = ({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPattern, taskIdPrefixPattern, tryNumber }: {
   after?: string;
   before?: string;
   dagId?: string;
@@ -405,6 +405,8 @@ export const UseEventLogServiceGetEventLogsKeyFn = ({ 
after, before, dagId, dagI
   offset?: number;
   orderBy?: string[];
   owner?: string;
+  ownerDisplayNamePattern?: string;
+  ownerDisplayNamePrefixPattern?: string;
   ownerPattern?: string;
   ownerPrefixPattern?: string;
   runId?: string;
@@ -414,7 +416,7 @@ export const UseEventLogServiceGetEventLogsKeyFn = ({ 
after, before, dagId, dagI
   taskIdPattern?: string;
   taskIdPrefixPattern?: string;
   tryNumber?: number;
-} = {}, queryKey?: Array<unknown>) => [useEventLogServiceGetEventLogsKey, 
...(queryKey ?? [{ after, before, dagId, dagIdPattern, dagIdPrefixPattern, 
event, eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }])];
+} = {}, queryKey?: Array<unknown>) => [useEventLogServiceGetEventLogsKey, 
...(queryKey ?? [{ after, before, dagId, dagIdPattern, dagIdPrefixPattern, 
event, eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerDisplayNamePattern, 
ownerDisplayNamePrefixPattern, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }])];
 export type ExtraLinksServiceGetExtraLinksDefaultResponse = 
Awaited<ReturnType<typeof ExtraLinksService.getExtraLinks>>;
 export type ExtraLinksServiceGetExtraLinksQueryResult<TData = 
ExtraLinksServiceGetExtraLinksDefaultResponse, TError = unknown> = 
UseQueryResult<TData, TError>;
 export const useExtraLinksServiceGetExtraLinksKey = 
"ExtraLinksServiceGetExtraLinks";
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts 
b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
index a97bde3062b..f435ab90302 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -758,16 +758,18 @@ export const ensureUseEventLogServiceGetEventLogData = 
(queryClient: QueryClient
 * @param data.taskIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `task_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.ownerPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `owner_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
+* @param data.ownerDisplayNamePattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `owner_display_name_prefix_pattern` on large tables — see 
"Filtering with pattern parameters".
 * @param data.eventPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `event_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.dagIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.taskIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.ownerPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
+* @param data.ownerDisplayNamePrefixPattern Case-sensitive, index-friendly 
prefix match. See "Filtering with pattern parameters".
 * @param data.eventPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @returns EventLogCollectionResponse Successful Response
 * @throws ApiError
 */
-export const ensureUseEventLogServiceGetEventLogsData = (queryClient: 
QueryClient, { after, before, dagId, dagIdPattern, dagIdPrefixPattern, event, 
eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }: {
+export const ensureUseEventLogServiceGetEventLogsData = (queryClient: 
QueryClient, { after, before, dagId, dagIdPattern, dagIdPrefixPattern, event, 
eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerDisplayNamePattern, 
ownerDisplayNamePrefixPattern, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }: {
   after?: string;
   before?: string;
   dagId?: string;
@@ -783,6 +785,8 @@ export const ensureUseEventLogServiceGetEventLogsData = 
(queryClient: QueryClien
   offset?: number;
   orderBy?: string[];
   owner?: string;
+  ownerDisplayNamePattern?: string;
+  ownerDisplayNamePrefixPattern?: string;
   ownerPattern?: string;
   ownerPrefixPattern?: string;
   runId?: string;
@@ -792,7 +796,7 @@ export const ensureUseEventLogServiceGetEventLogsData = 
(queryClient: QueryClien
   taskIdPattern?: string;
   taskIdPrefixPattern?: string;
   tryNumber?: number;
-} = {}) => queryClient.ensureQueryData({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerPattern, ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, 
taskId, taskIdPattern, taskIdPrefixPattern, tryNumber }), queryFn: () => 
EventLogService.getEventLogs({ after, before, dagId, dagIdPattern, dagIdPrefix 
[...]
+} = {}) => queryClient.ensureQueryData({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPattern, taskIdPrefixPattern, tryNumber }), queryFn: () => 
EventLogService.getEve [...]
 /**
 * Get Extra Links
 * Get extra links for task instance.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts 
b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
index 05732b1907f..a9e1144261a 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -758,16 +758,18 @@ export const prefetchUseEventLogServiceGetEventLog = 
(queryClient: QueryClient,
 * @param data.taskIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `task_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.ownerPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `owner_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
+* @param data.ownerDisplayNamePattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `owner_display_name_prefix_pattern` on large tables — see 
"Filtering with pattern parameters".
 * @param data.eventPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `event_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.dagIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.taskIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.ownerPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
+* @param data.ownerDisplayNamePrefixPattern Case-sensitive, index-friendly 
prefix match. See "Filtering with pattern parameters".
 * @param data.eventPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @returns EventLogCollectionResponse Successful Response
 * @throws ApiError
 */
-export const prefetchUseEventLogServiceGetEventLogs = (queryClient: 
QueryClient, { after, before, dagId, dagIdPattern, dagIdPrefixPattern, event, 
eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }: {
+export const prefetchUseEventLogServiceGetEventLogs = (queryClient: 
QueryClient, { after, before, dagId, dagIdPattern, dagIdPrefixPattern, event, 
eventPattern, eventPrefixPattern, excludedEvents, includedEvents, limit, 
mapIndex, offset, orderBy, owner, ownerDisplayNamePattern, 
ownerDisplayNamePrefixPattern, ownerPattern, ownerPrefixPattern, runId, 
runIdPattern, runIdPrefixPattern, taskId, taskIdPattern, taskIdPrefixPattern, 
tryNumber }: {
   after?: string;
   before?: string;
   dagId?: string;
@@ -783,6 +785,8 @@ export const prefetchUseEventLogServiceGetEventLogs = 
(queryClient: QueryClient,
   offset?: number;
   orderBy?: string[];
   owner?: string;
+  ownerDisplayNamePattern?: string;
+  ownerDisplayNamePrefixPattern?: string;
   ownerPattern?: string;
   ownerPrefixPattern?: string;
   runId?: string;
@@ -792,7 +796,7 @@ export const prefetchUseEventLogServiceGetEventLogs = 
(queryClient: QueryClient,
   taskIdPattern?: string;
   taskIdPrefixPattern?: string;
   tryNumber?: number;
-} = {}) => queryClient.prefetchQuery({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerPattern, ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, 
taskId, taskIdPattern, taskIdPrefixPattern, tryNumber }), queryFn: () => 
EventLogService.getEventLogs({ after, before, dagId, dagIdPattern, 
dagIdPrefixPa [...]
+} = {}) => queryClient.prefetchQuery({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPattern, taskIdPrefixPattern, tryNumber }), queryFn: () => 
EventLogService.getEvent [...]
 /**
 * Get Extra Links
 * Get extra links for task instance.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts 
b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
index 8e643f182d4..57a9970cdb7 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -758,16 +758,18 @@ export const useEventLogServiceGetEventLog = <TData = 
Common.EventLogServiceGetE
 * @param data.taskIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `task_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.ownerPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `owner_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
+* @param data.ownerDisplayNamePattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `owner_display_name_prefix_pattern` on large tables — see 
"Filtering with pattern parameters".
 * @param data.eventPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `event_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.dagIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.taskIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.ownerPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
+* @param data.ownerDisplayNamePrefixPattern Case-sensitive, index-friendly 
prefix match. See "Filtering with pattern parameters".
 * @param data.eventPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @returns EventLogCollectionResponse Successful Response
 * @throws ApiError
 */
-export const useEventLogServiceGetEventLogs = <TData = 
Common.EventLogServiceGetEventLogsDefaultResponse, TError = unknown, TQueryKey 
extends Array<unknown> = unknown[]>({ after, before, dagId, dagIdPattern, 
dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, excludedEvents, 
includedEvents, limit, mapIndex, offset, orderBy, owner, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPattern, taskIdPrefixPattern, tryNumber }: {
+export const useEventLogServiceGetEventLogs = <TData = 
Common.EventLogServiceGetEventLogsDefaultResponse, TError = unknown, TQueryKey 
extends Array<unknown> = unknown[]>({ after, before, dagId, dagIdPattern, 
dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, excludedEvents, 
includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPatte [...]
   after?: string;
   before?: string;
   dagId?: string;
@@ -783,6 +785,8 @@ export const useEventLogServiceGetEventLogs = <TData = 
Common.EventLogServiceGet
   offset?: number;
   orderBy?: string[];
   owner?: string;
+  ownerDisplayNamePattern?: string;
+  ownerDisplayNamePrefixPattern?: string;
   ownerPattern?: string;
   ownerPrefixPattern?: string;
   runId?: string;
@@ -792,7 +796,7 @@ export const useEventLogServiceGetEventLogs = <TData = 
Common.EventLogServiceGet
   taskIdPattern?: string;
   taskIdPrefixPattern?: string;
   tryNumber?: number;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerPattern, ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, 
taskId, taskIdPattern, taskIdPrefixPattern, tryNumber }, quer [...]
+} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskI [...]
 /**
 * Get Extra Links
 * Get extra links for task instance.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts 
b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
index 209b45e0200..acd2583f742 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -758,16 +758,18 @@ export const useEventLogServiceGetEventLogSuspense = 
<TData = Common.EventLogSer
 * @param data.taskIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `task_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.ownerPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `owner_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
+* @param data.ownerDisplayNamePattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `owner_display_name_prefix_pattern` on large tables — see 
"Filtering with pattern parameters".
 * @param data.eventPattern Case-insensitive substring match (SQL `ILIKE`). 
Slower than `event_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
 * @param data.dagIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.taskIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @param data.ownerPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
+* @param data.ownerDisplayNamePrefixPattern Case-sensitive, index-friendly 
prefix match. See "Filtering with pattern parameters".
 * @param data.eventPrefixPattern Case-sensitive, index-friendly prefix match. 
See "Filtering with pattern parameters".
 * @returns EventLogCollectionResponse Successful Response
 * @throws ApiError
 */
-export const useEventLogServiceGetEventLogsSuspense = <TData = 
Common.EventLogServiceGetEventLogsDefaultResponse, TError = unknown, TQueryKey 
extends Array<unknown> = unknown[]>({ after, before, dagId, dagIdPattern, 
dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, excludedEvents, 
includedEvents, limit, mapIndex, offset, orderBy, owner, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, 
taskIdPattern, taskIdPrefixPattern, tryNumber }: {
+export const useEventLogServiceGetEventLogsSuspense = <TData = 
Common.EventLogServiceGetEventLogsDefaultResponse, TError = unknown, TQueryKey 
extends Array<unknown> = unknown[]>({ after, before, dagId, dagIdPattern, 
dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, excludedEvents, 
includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, taskId, tas [...]
   after?: string;
   before?: string;
   dagId?: string;
@@ -783,6 +785,8 @@ export const useEventLogServiceGetEventLogsSuspense = 
<TData = Common.EventLogSe
   offset?: number;
   orderBy?: string[];
   owner?: string;
+  ownerDisplayNamePattern?: string;
+  ownerDisplayNamePrefixPattern?: string;
   ownerPattern?: string;
   ownerPrefixPattern?: string;
   runId?: string;
@@ -792,7 +796,7 @@ export const useEventLogServiceGetEventLogsSuspense = 
<TData = Common.EventLogSe
   taskIdPattern?: string;
   taskIdPrefixPattern?: string;
   tryNumber?: number;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerPattern, ownerPrefixPattern, runId, runIdPattern, runIdPrefixPattern, 
taskId, taskIdPattern, taskIdPrefixPattern, tryNumber [...]
+} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: 
Common.UseEventLogServiceGetEventLogsKeyFn({ after, before, dagId, 
dagIdPattern, dagIdPrefixPattern, event, eventPattern, eventPrefixPattern, 
excludedEvents, includedEvents, limit, mapIndex, offset, orderBy, owner, 
ownerDisplayNamePattern, ownerDisplayNamePrefixPattern, ownerPattern, 
ownerPrefixPattern, runId, runIdPattern, runIdPrefixPatter [...]
 /**
 * Get Extra Links
 * Get extra links for task instance.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts 
b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index 4466ec9d7da..94215ebd52e 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -2078,11 +2078,13 @@ export class EventLogService {
      * @param data.taskIdPattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `task_id_prefix_pattern` on large tables — see "Filtering 
with pattern parameters".
      * @param data.runIdPattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `run_id_prefix_pattern` on large tables — see "Filtering 
with pattern parameters".
      * @param data.ownerPattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `owner_prefix_pattern` on large tables — see "Filtering 
with pattern parameters".
+     * @param data.ownerDisplayNamePattern Case-insensitive substring match 
(SQL `ILIKE`). Slower than `owner_display_name_prefix_pattern` on large tables 
— see "Filtering with pattern parameters".
      * @param data.eventPattern Case-insensitive substring match (SQL 
`ILIKE`). Slower than `event_prefix_pattern` on large tables — see "Filtering 
with pattern parameters".
      * @param data.dagIdPrefixPattern Case-sensitive, index-friendly prefix 
match. See "Filtering with pattern parameters".
      * @param data.taskIdPrefixPattern Case-sensitive, index-friendly prefix 
match. See "Filtering with pattern parameters".
      * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix 
match. See "Filtering with pattern parameters".
      * @param data.ownerPrefixPattern Case-sensitive, index-friendly prefix 
match. See "Filtering with pattern parameters".
+     * @param data.ownerDisplayNamePrefixPattern Case-sensitive, 
index-friendly prefix match. See "Filtering with pattern parameters".
      * @param data.eventPrefixPattern Case-sensitive, index-friendly prefix 
match. See "Filtering with pattern parameters".
      * @returns EventLogCollectionResponse Successful Response
      * @throws ApiError
@@ -2110,11 +2112,13 @@ export class EventLogService {
                 task_id_pattern: data.taskIdPattern,
                 run_id_pattern: data.runIdPattern,
                 owner_pattern: data.ownerPattern,
+                owner_display_name_pattern: data.ownerDisplayNamePattern,
                 event_pattern: data.eventPattern,
                 dag_id_prefix_pattern: data.dagIdPrefixPattern,
                 task_id_prefix_pattern: data.taskIdPrefixPattern,
                 run_id_prefix_pattern: data.runIdPrefixPattern,
                 owner_prefix_pattern: data.ownerPrefixPattern,
+                owner_display_name_prefix_pattern: 
data.ownerDisplayNamePrefixPattern,
                 event_prefix_pattern: data.eventPrefixPattern
             },
             errors: {
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts 
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index 37a29af6add..8455306b581 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -3603,6 +3603,14 @@ export type GetEventLogsData = {
      */
     orderBy?: Array<(string)>;
     owner?: string | null;
+    /**
+     * Case-insensitive substring match (SQL `ILIKE`). Slower than 
`owner_display_name_prefix_pattern` on large tables — see "Filtering with 
pattern parameters".
+     */
+    ownerDisplayNamePattern?: string | null;
+    /**
+     * Case-sensitive, index-friendly prefix match. See "Filtering with 
pattern parameters".
+     */
+    ownerDisplayNamePrefixPattern?: string | null;
     /**
      * Case-insensitive substring match (SQL `ILIKE`). Slower than 
`owner_prefix_pattern` on large tables — see "Filtering with pattern 
parameters".
      */
diff --git a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx 
b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
index 9737a4a48ca..e193ac00dd6 100644
--- a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
@@ -66,7 +66,7 @@ const eventsColumn = (
   },
   {
     accessorKey: "owner",
-    cell: ({ row: { original } }) => original.owner_display_name ?? 
original.owner,
+    cell: ({ row: { original } }) => original.owner_display_name,
     enableSorting: true,
     header: translate("auditLog.columns.user"),
     meta: {
@@ -204,8 +204,8 @@ export const Events = () => {
     value: eventTypeFilter,
   });
   const ownerArg = useAdvancedSearchArg({
-    patternApiKey: "ownerPattern",
-    prefixApiKey: "ownerPrefixPattern",
+    patternApiKey: "ownerDisplayNamePattern",
+    prefixApiKey: "ownerDisplayNamePrefixPattern",
     storageKey: USER_PARAM,
     value: userFilter,
   });
diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py 
b/airflow-core/tests/unit/api_fastapi/auth/managers/models/__init__.py
similarity index 77%
copy from airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
copy to airflow-core/tests/unit/api_fastapi/auth/managers/models/__init__.py
index 7f060f3121e..13a83393a91 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
+++ b/airflow-core/tests/unit/api_fastapi/auth/managers/models/__init__.py
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,16 +14,3 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-from __future__ import annotations
-
-from abc import abstractmethod
-
-
-class BaseUser:
-    """User model interface."""
-
-    @abstractmethod
-    def get_id(self) -> str: ...
-
-    @abstractmethod
-    def get_name(self) -> str: ...
diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py 
b/airflow-core/tests/unit/api_fastapi/auth/managers/models/test_base_user.py
similarity index 65%
copy from airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
copy to 
airflow-core/tests/unit/api_fastapi/auth/managers/models/test_base_user.py
index 7f060f3121e..51ad5028dc9 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/models/base_user.py
+++ b/airflow-core/tests/unit/api_fastapi/auth/managers/models/test_base_user.py
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -17,14 +16,18 @@
 # under the License.
 from __future__ import annotations
 
-from abc import abstractmethod
+from airflow.api_fastapi.auth.managers.models.base_user import BaseUser
+
+
+class UserWithoutDisplayName(BaseUser):
+    """An auth manager user predating get_display_name (only get_id / get_name 
defined)."""
 
+    def get_id(self) -> str:
+        return "user-id"
 
-class BaseUser:
-    """User model interface."""
+    def get_name(self) -> str:
+        return "user-name"
 
-    @abstractmethod
-    def get_id(self) -> str: ...
 
-    @abstractmethod
-    def get_name(self) -> str: ...
+def test_get_display_name_defaults_to_get_name():
+    assert UserWithoutDisplayName().get_display_name() == "user-name"
diff --git 
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_event_logs.py 
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_event_logs.py
index 564c383a1ff..871692f98d2 100644
--- 
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_event_logs.py
+++ 
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_event_logs.py
@@ -403,6 +403,20 @@ class TestGetEventLogs(TestEventLogsEndpoint):
         assert event_log["owner"] == OWNER_AIRFLOW
         assert event_log["owner_display_name"] == OWNER_AIRFLOW
 
+    def test_get_event_logs_filters_by_owner_display_name_pattern(self, 
test_client):
+        response = test_client.get("/eventLogs", 
params={"owner_display_name_pattern": "est Own"})
+
+        assert response.status_code == 200
+        events = {event_log["event"] for event_log in 
response.json()["event_logs"]}
+        assert events == {EVENT_WITH_OWNER, EVENT_WITH_OWNER_AND_TASK_INSTANCE}
+
+    def test_get_event_logs_filters_by_owner_display_name_prefix_pattern(self, 
test_client):
+        response = test_client.get("/eventLogs", 
params={"owner_display_name_prefix_pattern": "Test"})
+
+        assert response.status_code == 200
+        events = {event_log["event"] for event_log in 
response.json()["event_logs"]}
+        assert events == {EVENT_WITH_OWNER, EVENT_WITH_OWNER_AND_TASK_INSTANCE}
+
     # Ordering of nulls values is DB specific.
     @pytest.mark.backend("sqlite")
     @pytest.mark.parametrize(
diff --git a/airflow-core/tests/unit/api_fastapi/logging/test_decorators.py 
b/airflow-core/tests/unit/api_fastapi/logging/test_decorators.py
index 41b9883d6d3..2adffbe4544 100644
--- a/airflow-core/tests/unit/api_fastapi/logging/test_decorators.py
+++ b/airflow-core/tests/unit/api_fastapi/logging/test_decorators.py
@@ -16,14 +16,20 @@
 # under the License.
 from __future__ import annotations
 
+import asyncio
 import json
+from unittest.mock import MagicMock
 
 import pytest
+from fastapi import Request
+from sqlalchemy.orm import Session
 
+from airflow.api_fastapi.auth.managers.models.base_user import BaseUser
 from airflow.api_fastapi.logging.decorators import (
     _mask_connection_fields,
     _mask_variable_fields,
     _sanitize_for_stdlib_log,
+    action_logging,
 )
 
 
@@ -122,3 +128,28 @@ class TestMaskVariableFields:
     def test_value_without_key_is_still_masked(self):
         result = _mask_variable_fields({"value": "secretval"})
         assert result == {"value": "***"}
+
+
+class TestActionLoggingUserFields:
+    """The audit Log records the raw identifier in ``owner`` and the 
human-friendly
+    ``get_display_name()`` in ``owner_display_name``."""
+
+    def test_owner_and_display_name_use_the_matching_user_methods(self):
+        class FakeUser(BaseUser):
+            def get_id(self) -> str:
+                return "id"
+
+            def get_name(self) -> str:
+                return "jdoe"
+
+            def get_display_name(self) -> str:
+                return "Jane Doe"
+
+        request = Request({"type": "http", "method": "GET", "headers": [], 
"query_string": b""})
+        session = MagicMock(spec=Session)
+
+        asyncio.run(action_logging(event="test_event")(request=request, 
session=session, user=FakeUser()))
+
+        (logged,) = session.add.call_args.args
+        assert logged.owner == "jdoe"
+        assert logged.owner_display_name == "Jane Doe"
diff --git 
a/providers/fab/src/airflow/providers/fab/auth_manager/models/__init__.py 
b/providers/fab/src/airflow/providers/fab/auth_manager/models/__init__.py
index 598f13b2219..ecdac36f421 100644
--- a/providers/fab/src/airflow/providers/fab/auth_manager/models/__init__.py
+++ b/providers/fab/src/airflow/providers/fab/auth_manager/models/__init__.py
@@ -363,6 +363,9 @@ class User(Model, BaseUser):
     def get_full_name(self):
         return f"{self.first_name} {self.last_name}"
 
+    def get_display_name(self) -> str:
+        return self.get_full_name()
+
     def __repr__(self):
         return self.get_full_name()
 
diff --git 
a/providers/fab/tests/unit/fab/auth_manager/models/test_user_model.py 
b/providers/fab/tests/unit/fab/auth_manager/models/test_user_model.py
index f780871676e..c054463c303 100644
--- a/providers/fab/tests/unit/fab/auth_manager/models/test_user_model.py
+++ b/providers/fab/tests/unit/fab/auth_manager/models/test_user_model.py
@@ -36,3 +36,10 @@ def test_get_id_returns_str(user_id: int, expected_id: str) 
-> None:
     result = user.get_id()
     assert isinstance(result, str), f"Expected str, got {type(result)}"
     assert result == expected_id
+
+
+def test_get_display_name_uses_full_name() -> None:
+    user = User()
+    user.first_name = "Jane"
+    user.last_name = "Doe"
+    assert user.get_display_name() == "Jane Doe"

Reply via email to