From cc819e04b62c52a0f566c5e86e171a121631ae88 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Sun, 8 May 2022 17:07:12 +0200 Subject: [PATCH] repos: configure source for credential lookup With this change users no longer need to configure source url explicitly via `repositories` configuration values when credentials are required. --- src/poetry/repositories/http.py | 1 + src/poetry/utils/authenticator.py | 8 ++++ tests/repositories/test_legacy_repository.py | 43 ++++++++++++++++++++ tests/utils/test_authenticator.py | 36 ++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/src/poetry/repositories/http.py b/src/poetry/repositories/http.py index 02d8210c46c..0a43f1e6600 100644 --- a/src/poetry/repositories/http.py +++ b/src/poetry/repositories/http.py @@ -47,6 +47,7 @@ def __init__( cache_id=name, disable_cache=disable_cache, ) + self._authenticator.add_repository(name, url) @property def session(self) -> Authenticator: diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 01af47887eb..47cbd20ac13 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -323,6 +323,14 @@ def configured_repositories(self) -> dict[str, AuthenticatorRepositoryConfig]: return self._configured_repositories + def reset_credentials_cache(self) -> None: + self.get_repository_config_for_url.cache_clear() + self._credentials = {} + + def add_repository(self, name: str, url: str) -> None: + self.configured_repositories[name] = AuthenticatorRepositoryConfig(name, url) + self.reset_credentials_cache() + def get_certs_for_url(self, url: str) -> dict[str, Path | None]: if url not in self._certs: self._certs[url] = self._get_certs_for_url(url) diff --git a/tests/repositories/test_legacy_repository.py b/tests/repositories/test_legacy_repository.py index 0c5f0111432..baee9cb527c 100644 --- a/tests/repositories/test_legacy_repository.py +++ b/tests/repositories/test_legacy_repository.py @@ -1,5 +1,7 @@ from __future__ import annotations +import base64 +import re import shutil from pathlib import Path @@ -27,6 +29,8 @@ from _pytest.monkeypatch import MonkeyPatch + from poetry.config.config import Config + @pytest.fixture(autouse=True) def _use_simple_keyring(with_simple_keyring: None) -> None: @@ -418,3 +422,42 @@ def get_mock(url: str, raise_for_status: bool = True) -> requests.Response: monkeypatch.setattr(repo.session, "get", get_mock) assert repo._get_page("/foo")._url == "http://legacy.redirect.bar/foo/" + + +@pytest.mark.parametrize( + ("repositories",), + [ + ({},), + # ensure path is respected + ({"publish": {"url": "https://foo.bar/legacy"}},), + # ensure path length does not give incorrect results + ({"publish": {"url": "https://foo.bar/upload/legacy"}},), + ], +) +def test_authenticator_with_implicit_repository_configuration( + http: type[httpretty.httpretty], + config: Config, + repositories: dict[str, dict[str, str]], +) -> None: + http.register_uri( + http.GET, + re.compile("^https?://foo.bar/(.+?)$"), + ) + + config.merge( + { + "repositories": repositories, + "http-basic": { + "source": {"username": "foo", "password": "bar"}, + "publish": {"username": "baz", "password": "qux"}, + }, + } + ) + + repo = LegacyRepository(name="source", url="https://foo.bar/simple", config=config) + repo._get_page("/foo") + + request = http.last_request() + + basic_auth = base64.b64encode(b"foo:bar").decode() + assert request.headers["Authorization"] == f"Basic {basic_auth}" diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 2d9d282e1d1..dd1666036ab 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -524,3 +524,39 @@ def test_authenticator_azure_feed_guid_credentials( basic_auth = base64.b64encode(b"baz:qux").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}" + + +def test_authenticator_add_repository( + config: Config, + mock_remote: None, + http: type[httpretty.httpretty], + with_simple_keyring: None, + dummy_keyring: DummyBackend, +): + config.merge( + { + "http-basic": { + "source": {"username": "foo", "password": "bar"}, + }, + } + ) + + authenticator = Authenticator(config, NullIO()) + + authenticator.request( + "get", + "https://foo.bar/simple/a/1.0.0/a-1.0.0.whl", + ) + request = http.last_request() + assert "Authorization" not in request.headers + + authenticator.add_repository("source", "https://foo.bar/simple/") + + authenticator.request( + "get", + "https://foo.bar/simple/a/1.0.0/a-1.0.0.whl", + ) + request = http.last_request() + + basic_auth = base64.b64encode(b"foo:bar").decode() + assert request.headers["Authorization"] == f"Basic {basic_auth}"