This is an automated email from the ASF dual-hosted git repository.
eladkal 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 12a760f6df Affix webserver access_denied warning to be configurable
(#33022)
12a760f6df is described below
commit 12a760f6df831c1d53d035e4d169a69887e8bb26
Author: Amogh Desai <[email protected]>
AuthorDate: Thu Aug 3 14:34:31 2023 +0530
Affix webserver access_denied warning to be configurable (#33022)
* Affix webserver access_denied warning to be configurable
---
airflow/config_templates/config.yml | 7 +++++++
airflow/www/auth.py | 6 +++++-
tests/www/test_security.py | 18 ++++++++++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/airflow/config_templates/config.yml
b/airflow/config_templates/config.yml
index b550c25932..6cd249a9ce 100644
--- a/airflow/config_templates/config.yml
+++ b/airflow/config_templates/config.yml
@@ -1349,6 +1349,13 @@ operators:
webserver:
description: ~
options:
+ access_denied_message:
+ description: |
+ The message displayed when a user attempts to execute actions beyond
their authorised privileges.
+ version_added: 2.7.0
+ type: string
+ example: ~
+ default: "Access is Denied"
config_file:
description: |
Path of webserver config file used for configuring the webserver
parameters
diff --git a/airflow/www/auth.py b/airflow/www/auth.py
index 9afe995054..f4cb53886e 100644
--- a/airflow/www/auth.py
+++ b/airflow/www/auth.py
@@ -28,6 +28,10 @@ from airflow.www.extensions.init_auth_manager import
get_auth_manager
T = TypeVar("T", bound=Callable)
+def get_access_denied_message():
+ return conf.get("webserver", "access_denied_message")
+
+
def has_access(permissions: Sequence[tuple[str, str]] | None = None) ->
Callable[[T], T]:
"""Factory for decorator that checks current user's permissions against
required permissions."""
@@ -59,7 +63,7 @@ def has_access(permissions: Sequence[tuple[str, str]] | None
= None) -> Callable
403,
)
else:
- access_denied = "Access is Denied"
+ access_denied = get_access_denied_message()
flash(access_denied, "danger")
return redirect(get_auth_manager().get_url_login(next=request.url))
diff --git a/tests/www/test_security.py b/tests/www/test_security.py
index 99659de2c7..dec262f25f 100644
--- a/tests/www/test_security.py
+++ b/tests/www/test_security.py
@@ -20,6 +20,7 @@ from __future__ import annotations
import contextlib
import datetime
import logging
+import os
from unittest import mock
from unittest.mock import patch
@@ -32,12 +33,14 @@ from sqlalchemy import Column, Date, Float, Integer, String
from airflow.auth.managers.fab.auth.anonymous_user import AnonymousUser
from airflow.auth.managers.fab.fab_auth_manager import FabAuthManager
from airflow.auth.managers.fab.models import User, assoc_permission_role
+from airflow.configuration import initialize_config
from airflow.exceptions import AirflowException
from airflow.models import DagModel
from airflow.models.base import Base
from airflow.models.dag import DAG
from airflow.security import permissions
from airflow.www import app as application
+from airflow.www.auth import get_access_denied_message
from airflow.www.utils import CustomSQLAInterface
from tests.test_utils.api_connexion_utils import (
create_user,
@@ -969,3 +972,18 @@ def test_users_can_be_found(app, security_manager,
session, caplog):
assert len(users) == 1
delete_user(app, "Test")
assert "Error adding new user to database" in caplog.text
+
+
+def test_default_access_denied_message():
+ initialize_config()
+ assert get_access_denied_message() == "Access is Denied"
+
+
+def test_custom_access_denied_message():
+ with mock.patch.dict(
+ os.environ,
+ {"AIRFLOW__WEBSERVER__ACCESS_DENIED_MESSAGE": "My custom access denied
message"},
+ clear=True,
+ ):
+ initialize_config()
+ assert get_access_denied_message() == "My custom access denied message"