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

pierrejeambrun pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new 091d852122c [v3-1-test] Fix permissions on get_event_logs endpoint 
(#60936) (#60958)
091d852122c is described below

commit 091d852122c30ce017fddd9763361d3147b1b3f3
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jan 23 17:21:27 2026 +0100

    [v3-1-test] Fix permissions on get_event_logs endpoint (#60936) (#60958)
    
    * Fix permissions on get_event_logs endpoint
    
    * Fix CI
    (cherry picked from commit c064739d3a7686834eca6773ed6497e423589a9d)
    
    Co-authored-by: Pierre Jeambrun <[email protected]>
---
 .../api_fastapi/core_api/routes/public/event_logs.py       |  9 ++++++++-
 airflow-core/src/airflow/api_fastapi/core_api/security.py  | 14 ++++++++++++++
 .../api_fastapi/core_api/routes/public/test_event_logs.py  |  4 ++--
 3 files changed, 24 insertions(+), 3 deletions(-)

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 8909b5ff1bc..529fbb94a6b 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
@@ -43,7 +43,11 @@ from airflow.api_fastapi.core_api.datamodels.event_logs 
import (
     EventLogResponse,
 )
 from airflow.api_fastapi.core_api.openapi.exceptions import 
create_openapi_http_exception_doc
-from airflow.api_fastapi.core_api.security import DagAccessEntity, 
requires_access_dag
+from airflow.api_fastapi.core_api.security import (
+    DagAccessEntity,
+    ReadableEventLogsFilterDep,
+    requires_access_dag,
+)
 from airflow.models import Log
 
 event_logs_router = AirflowRouter(tags=["Event Log"], prefix="/eventLogs")
@@ -126,6 +130,7 @@ def get_event_logs(
     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"))],
     event_pattern: Annotated[_SearchParam, 
Depends(search_param_factory(Log.event, "event_pattern"))],
+    readable_event_logs_filter: ReadableEventLogsFilterDep,
 ) -> EventLogCollectionResponse:
     """Get all Event Logs."""
     query = select(Log).options(joinedload(Log.task_instance), 
joinedload(Log.dag_model))
@@ -151,6 +156,8 @@ def get_event_logs(
             run_id_pattern,
             owner_pattern,
             event_pattern,
+            # Permission
+            readable_event_logs_filter,
         ],
         offset=offset,
         limit=limit,
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/security.py 
b/airflow-core/src/airflow/api_fastapi/core_api/security.py
index 5e9fae52e65..ed75cf305ae 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/security.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/security.py
@@ -25,6 +25,7 @@ from fastapi import Depends, HTTPException, Request, status
 from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer, 
OAuth2PasswordBearer
 from jwt import ExpiredSignatureError, InvalidTokenError
 from pydantic import NonNegativeInt
+from sqlalchemy import or_
 
 from airflow.api_fastapi.app import get_auth_manager
 from airflow.api_fastapi.auth.managers.base_auth_manager import 
COOKIE_NAME_JWT_TOKEN
@@ -62,6 +63,7 @@ from airflow.configuration import conf
 from airflow.models import Connection, Pool, Variable
 from airflow.models.dag import DagModel, DagRun, DagTag
 from airflow.models.dagwarning import DagWarning
+from airflow.models.log import Log
 from airflow.models.taskinstance import TaskInstance as TI
 from airflow.models.xcom import XComModel
 
@@ -170,6 +172,15 @@ class PermittedDagWarningFilter(PermittedDagFilter):
         return select.where(DagWarning.dag_id.in_(self.value))
 
 
+class PermittedEventLogFilter(PermittedDagFilter):
+    """A parameter that filters the permitted even logs for the user."""
+
+    def to_orm(self, select: Select) -> Select:
+        # Event Logs not related to Dags have dag_id as None and are always 
returned.
+        # return select.where(Log.dag_id.in_(self.value or set()) or 
Log.dag_id.is_(None))
+        return select.where(or_(Log.dag_id.in_(self.value or set()), 
Log.dag_id.is_(None)))
+
+
 class PermittedTIFilter(PermittedDagFilter):
     """A parameter that filters the permitted task instances for the user."""
 
@@ -223,6 +234,9 @@ ReadableDagWarningsFilterDep = Annotated[
 ReadableTIFilterDep = Annotated[
     PermittedTIFilter, Depends(permitted_dag_filter_factory("GET", 
PermittedTIFilter))
 ]
+ReadableEventLogsFilterDep = Annotated[
+    PermittedTIFilter, Depends(permitted_dag_filter_factory("GET", 
PermittedEventLogFilter))
+]
 ReadableXComFilterDep = Annotated[
     PermittedXComFilter, Depends(permitted_dag_filter_factory("GET", 
PermittedXComFilter))
 ]
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 dd87e8d7fac..0d68107ea1a 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
@@ -302,7 +302,7 @@ class TestGetEventLogs(TestEventLogsEndpoint):
     def test_get_event_logs(
         self, test_client, query_params, expected_status_code, 
expected_total_entries, expected_events
     ):
-        with assert_queries_count(2):
+        with assert_queries_count(3):
             response = test_client.get("/eventLogs", params=query_params)
         assert response.status_code == expected_status_code
         if expected_status_code != 200:
@@ -341,7 +341,7 @@ class TestGetEventLogs(TestEventLogsEndpoint):
     def test_get_event_logs_order_by(
         self, test_client, query_params, expected_status_code, 
expected_total_entries, expected_events
     ):
-        with assert_queries_count(2):
+        with assert_queries_count(3):
             response = test_client.get("/eventLogs", params=query_params)
         assert response.status_code == expected_status_code
         if expected_status_code != 200:

Reply via email to