Skip to content

Commit

Permalink
Fix regression when using empty username/password
Browse files Browse the repository at this point in the history
This change fixes a regression in the password manager that disallowed
the use of empty username or password as required by some self-hosted
repositories.

Relates-to: #9079 #2538
  • Loading branch information
abn committed Nov 17, 2024
1 parent 6e1bf8b commit a923878
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 15 deletions.
15 changes: 11 additions & 4 deletions src/poetry/utils/password_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,25 @@ def delete_pypi_token(self, repo_name: str) -> None:
def get_http_auth(self, repo_name: str) -> dict[str, str | None] | None:
username = self._config.get(f"http-basic.{repo_name}.username")
password = self._config.get(f"http-basic.{repo_name}.password")
if not username and not password:

# we only return None if both values are None or ""
# password can be None at this stage with the username ""
if (username is password is None) or (username == password == ""):
return None

if not password:
if self.use_keyring:
password = self.keyring.get_password(repo_name, username)
else:
elif not username:
# at this tage if username is "" or None, auth is invalid
return None

if not username and not password:
return None

return {
"username": username,
"password": password,
"username": username or "",
"password": password or "",
}

def set_http_password(self, repo_name: str, username: str, password: str) -> None:
Expand Down
55 changes: 44 additions & 11 deletions tests/utils/test_password_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,36 @@ def test_set_http_password(
assert "password" not in auth


@pytest.mark.parametrize(
("username", "password", "is_valid"),
[
("bar", "baz", True),
("", "baz", True),
("bar", "", True),
("", "", False),
],
)
def test_get_http_auth(
config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend
username: str,
password: str,
is_valid: bool,
config: Config,
with_simple_keyring: None,
dummy_keyring: DummyBackend,
) -> None:
dummy_keyring.set_password("poetry-repository-foo", "bar", "baz")
config.auth_config_source.add_property("http-basic.foo", {"username": "bar"})
dummy_keyring.set_password("poetry-repository-foo", username, password)
config.auth_config_source.add_property("http-basic.foo", {"username": username})
manager = PasswordManager(config)

assert PoetryKeyring.is_available()
auth = manager.get_http_auth("foo")
assert auth is not None

assert auth["username"] == "bar"
assert auth["password"] == "baz"
if is_valid:
assert auth is not None
assert auth["username"] == username
assert auth["password"] == password
else:
assert auth is None


def test_delete_http_password(
Expand Down Expand Up @@ -113,20 +130,36 @@ def test_set_http_password_with_unavailable_backend(
assert auth["password"] == "baz"


@pytest.mark.parametrize(
("username", "password", "is_valid"),
[
("bar", "baz", True),
("", "baz", True),
("bar", "", True),
("", "", False),
],
)
def test_get_http_auth_with_unavailable_backend(
config: Config, with_fail_keyring: None
username: str,
password: str,
is_valid: bool,
config: Config,
with_fail_keyring: None,
) -> None:
config.auth_config_source.add_property(
"http-basic.foo", {"username": "bar", "password": "baz"}
"http-basic.foo", {"username": username, "password": password}
)
manager = PasswordManager(config)

assert not PoetryKeyring.is_available()
auth = manager.get_http_auth("foo")
assert auth is not None

assert auth["username"] == "bar"
assert auth["password"] == "baz"
if is_valid:
assert auth is not None
assert auth["username"] == username
assert auth["password"] == password
else:
assert auth is None


def test_delete_http_password_with_unavailable_backend(
Expand Down

0 comments on commit a923878

Please sign in to comment.