You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by vi...@apache.org on 2025/11/26 16:03:21 UTC
(airflow) branch main updated: Do not delete users from simple auth manager user file (#58688)
This is an automated email from the ASF dual-hosted git repository.
vincbeck 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 97cd1c9c990 Do not delete users from simple auth manager user file (#58688)
97cd1c9c990 is described below
commit 97cd1c9c99030be89cebaddc2e342359fc01b5b8
Author: Vincent <97...@users.noreply.github.com>
AuthorDate: Wed Nov 26 11:03:13 2025 -0500
Do not delete users from simple auth manager user file (#58688)
---
.../auth/managers/simple/services/login.py | 2 +-
.../auth/managers/simple/simple_auth_manager.py | 19 ++++++-------------
.../auth/managers/simple/services/test_login.py | 3 +--
.../auth/managers/simple/test_simple_auth_manager.py | 7 ++-----
4 files changed, 10 insertions(+), 21 deletions(-)
diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/services/login.py b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/services/login.py
index d4e606ebfc3..3ecfd1cd294 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/services/login.py
+++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/services/login.py
@@ -52,7 +52,7 @@ class SimpleAuthManagerLogin:
)
users = SimpleAuthManager.get_users()
- passwords = SimpleAuthManager.get_passwords(users)
+ passwords = SimpleAuthManager.get_passwords()
found_users = [
user
for user in users
diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/simple_auth_manager.py b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/simple_auth_manager.py
index 301526d7da5..15834a2cfb1 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/simple_auth_manager.py
+++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/simple_auth_manager.py
@@ -102,10 +102,10 @@ class SimpleAuthManager(BaseAuthManager[SimpleAuthManagerUser]):
return [{"username": username, "role": role} for username, role in users]
@staticmethod
- def get_passwords(users: list[dict[str, str]]) -> dict[str, str]:
+ def get_passwords() -> dict[str, str]:
password_file = SimpleAuthManager.get_generated_password_file()
with open(password_file, "r+") as file:
- return SimpleAuthManager._get_passwords(users=users, stream=file)[0]
+ return SimpleAuthManager._get_passwords(file)
def init(self) -> None:
is_simple_auth_manager_all_admins = conf.getboolean("core", "simple_auth_manager_all_admins")
@@ -121,7 +121,8 @@ class SimpleAuthManager(BaseAuthManager[SimpleAuthManagerUser]):
# Fastapi spins up N workers, so this method is called N times in N different processes
# This needs to be called only once so we use the file ``password_file`` as locking mechanism
fcntl.flock(file, fcntl.LOCK_EX | fcntl.LOCK_NB)
- passwords, changed = self._get_passwords(users=users, stream=file)
+ passwords = self._get_passwords(stream=file)
+ changed = False
for user in users:
if user["username"] not in passwords:
# User does not exist in the file, adding it
@@ -359,7 +360,7 @@ class SimpleAuthManager(BaseAuthManager[SimpleAuthManagerUser]):
return role.order >= allow_role.order
@staticmethod
- def _get_passwords(users: list[dict[str, str]], stream: TextIO) -> tuple[dict[str, str], bool]:
+ def _get_passwords(stream: TextIO) -> dict[str, str]:
try:
# Read passwords from file
stream.seek(0)
@@ -369,15 +370,7 @@ class SimpleAuthManager(BaseAuthManager[SimpleAuthManagerUser]):
log.error("Error decoding JSON from file %s", stream.name)
raise
- usernames = {user["username"] for user in users}
- changed = bool(user_passwords_from_file.keys() - usernames)
- user_passwords_from_file = {
- username: password
- for username, password in user_passwords_from_file.items()
- if username in usernames
- }
-
- return user_passwords_from_file, changed
+ return user_passwords_from_file
@staticmethod
def _generate_password() -> str:
diff --git a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/services/test_login.py b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/services/test_login.py
index 9c8299a8a21..e6a843c75cc 100644
--- a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/services/test_login.py
+++ b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/services/test_login.py
@@ -56,8 +56,7 @@ class TestLogin:
}
):
auth_manager.init()
- users = auth_manager.get_users()
- passwords = auth_manager.get_passwords(users=users)
+ passwords = auth_manager.get_passwords()
result = SimpleAuthManagerLogin.create_token(
body=LoginBody(username=test_user, password=passwords.get(test_user, "invalid_password")),
expiration_time_in_seconds=1,
diff --git a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_simple_auth_manager.py b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_simple_auth_manager.py
index 43699192fee..f5566be6595 100644
--- a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_simple_auth_manager.py
+++ b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_simple_auth_manager.py
@@ -47,7 +47,6 @@ class TestSimpleAuthManager:
("", {}),
('{"test1": "test1"}', {"test1": "test1"}),
('{"test1": "test1", "test2": "test2"}', {"test1": "test1", "test2": "test2"}),
- ('{"test1": "test1", "test2": "test2", "test3": "test3"}', {"test1": "test1", "test2": "test2"}),
],
)
def test_get_passwords(self, auth_manager, file_content, expected):
@@ -58,8 +57,7 @@ class TestSimpleAuthManager:
):
with open(auth_manager.get_generated_password_file(), "w") as file:
file.write(file_content)
- users = auth_manager.get_users()
- passwords = auth_manager.get_passwords(users)
+ passwords = auth_manager.get_passwords()
assert passwords == expected
def test_init_with_default_user(self, auth_manager):
@@ -87,8 +85,7 @@ class TestSimpleAuthManager:
("file_content", "expected"),
[
({"test1": "test1"}, {"test1": "test1"}),
- ({"test1": "test1", "test2": "test2"}, {"test1": "test1"}),
- ({"test2": "test2", "test3": "test3"}, {"test1": mock.ANY}),
+ ({"test2": "test2", "test3": "test3"}, {"test1": mock.ANY, "test2": "test2", "test3": "test3"}),
],
)
def test_init_with_users_with_password(self, auth_manager, file_content, expected):