From 9831fec01902b33507e682d97e9b097fdd2d641b Mon Sep 17 00:00:00 2001 From: Ziga Lesjak Date: Wed, 13 Sep 2023 12:06:01 +0000 Subject: [PATCH 1/2] Support percent encoded userinfo as per RFC3986 --- dslr/config.py | 6 +++--- tests/test_cli.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/dslr/config.py b/dslr/config.py index 87e4478..248284e 100644 --- a/dslr/config.py +++ b/dslr/config.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from urllib.parse import urlparse +from urllib.parse import unquote, urlparse from .console import console @@ -28,8 +28,8 @@ def initialize(self, *, url: str, debug: bool): self.db = DatabaseConnection( host=parsed.hostname or "", port=parsed.port or 5432, - username=parsed.username or "", - password=parsed.password or "", + username=unquote(parsed.username or ""), + password=unquote(parsed.password or ""), name=parsed.path[1:], ) diff --git a/tests/test_cli.py b/tests/test_cli.py index 8e88ca2..baa38d5 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,7 +1,9 @@ import os from datetime import datetime +from itertools import product from typing import Any, List, Tuple from unittest import TestCase, mock +from urllib.parse import quote from click.testing import CliRunner @@ -305,3 +307,40 @@ def test_settings_preference_order(self, mock_cli_settings, mock_get_snapshots): mock.call(debug=False, url="postgres://cli:pw@test:5432/my_db"), ], ) + + @mock.patch("dslr.config.DatabaseConnection") + def test_encoded_username_password( + self, mock_database_connection, mock_get_snapshots + ): + usernames = ["user", "user@example.com"] + passwords = ["pw", "f4A$#%&?!_@:asvb"] + + for username, password in product(usernames, passwords): + with self.subTest(username=username, password=password): + mock_database_connection.reset_mock() + + username_encoded = quote(username) + password_encoded = quote(password) + + # DATABASE_URL environment variable is used + with mock.patch.dict( + os.environ, + { + "DATABASE_URL": ( + f"postgres://{username_encoded}:{password_encoded}" + "@test:5432/my_db" + ) + }, + ): + runner = CliRunner() + result = runner.invoke(cli.cli, ["list"]) + + self.assertEqual(result.exit_code, 0) + + self.assertEqual(1, mock_database_connection.call_count) + self.assertEqual( + mock_database_connection.call_args.kwargs["username"], username + ) + self.assertEqual( + mock_database_connection.call_args.kwargs["password"], password + ) From 8006a742880926013eada2ac5dd440cc5ae3b518 Mon Sep 17 00:00:00 2001 From: Ziga Lesjak Date: Tue, 9 Jan 2024 19:42:39 +0000 Subject: [PATCH 2/2] Fix test for python 3.7 --- tests/test_cli.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index baa38d5..270fb9f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -338,9 +338,7 @@ def test_encoded_username_password( self.assertEqual(result.exit_code, 0) self.assertEqual(1, mock_database_connection.call_count) - self.assertEqual( - mock_database_connection.call_args.kwargs["username"], username - ) - self.assertEqual( - mock_database_connection.call_args.kwargs["password"], password - ) + + _, call_kwargs = mock_database_connection.call_args + self.assertEqual(call_kwargs["username"], username) + self.assertEqual(call_kwargs["password"], password)