From eda089334864547e18b71cb22fa231872edd4e8b Mon Sep 17 00:00:00 2001 From: Jed Cunningham <66968678+jedcunningham@users.noreply.github.com> Date: Tue, 1 Nov 2022 16:55:02 -0700 Subject: [PATCH] Fix behavior of `_` when searching for DAGs (#27448) On the homepage, when you search for DAGs, `_` wasn't behaving as most people might expect since it is a single character wildcard in SQL. We will automatically escape it now. --- airflow/www/views.py | 5 +++-- tests/www/views/test_views_home.py | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/airflow/www/views.py b/airflow/www/views.py index bc03f42f04f0f..b134b334e29e6 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -654,9 +654,10 @@ def index(self): dags_query = session.query(DagModel).filter(~DagModel.is_subdag, DagModel.is_active) if arg_search_query: + escaped_arg_search_query = arg_search_query.replace("_", r"\_") dags_query = dags_query.filter( - DagModel.dag_id.ilike('%' + arg_search_query + '%') - | DagModel.owners.ilike('%' + arg_search_query + '%') + DagModel.dag_id.ilike("%" + escaped_arg_search_query + "%", escape="\\") + | DagModel.owners.ilike("%" + escaped_arg_search_query + "%", escape="\\") ) if arg_tags_filter: diff --git a/tests/www/views/test_views_home.py b/tests/www/views/test_views_home.py index e7641ed955fe8..e859abe6059e7 100644 --- a/tests/www/views/test_views_home.py +++ b/tests/www/views/test_views_home.py @@ -118,7 +118,7 @@ def client_single_dag(app, user_single_dag): ) -TEST_FILTER_DAG_IDS = ["filter_test_1", "filter_test_2", "a_first_dag_id_asc"] +TEST_FILTER_DAG_IDS = ["filter_test_1", "filter_test_2", "a_first_dag_id_asc", "filter.test"] def _process_file(file_path, session): @@ -185,6 +185,14 @@ def test_home_dag_list_filtered_singledag_user(working_dags, client_single_dag): check_content_not_in_response(f"dag_id={dag_id}", resp) +def test_home_dag_list_search(working_dags, user_client): + resp = user_client.get("home?search=filter_test", follow_redirects=True) + check_content_in_response("dag_id=filter_test_1", resp) + check_content_in_response("dag_id=filter_test_2", resp) + check_content_not_in_response("dag_id=filter.test", resp) + check_content_not_in_response("dag_id=a_first_dag_id_asc", resp) + + def test_home_robots_header_in_response(user_client): # Responses should include X-Robots-Tag header resp = user_client.get("home", follow_redirects=True)