From 5fd11652c9b42836ab272a64dd54ae0797c6a107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=BDborn=C3=BD=20Adam?= Date: Tue, 10 Oct 2023 09:23:08 +0200 Subject: [PATCH] Escape username and password in repository URL --- src/Service/GitRepositoryService.php | 38 ++++++++------ .../Service/GitRepositoryServiceTest.php | 50 +++++++++++++++++++ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/src/Service/GitRepositoryService.php b/src/Service/GitRepositoryService.php index 02c0e703..3dd7b9cb 100644 --- a/src/Service/GitRepositoryService.php +++ b/src/Service/GitRepositoryService.php @@ -40,20 +40,7 @@ public function clone( $branchArgument = ['-b', $branch]; } - $parsedUrl = parse_url($repositoryUrl); - if (!$parsedUrl || !array_key_exists('host', $parsedUrl)) { - throw new UserException(sprintf('Wrong URL format "%s"', $repositoryUrl)); - } - if ($username && $password) { - $url = str_replace($parsedUrl['host'], sprintf( - '%s:%s@%s', - $username, - $password, - $parsedUrl['host'] - ), $repositoryUrl); - } else { - $url = $repositoryUrl; - } + $url = $this->getUrl($repositoryUrl, $username, $password); try { $process = new Process(['git', 'clone', ...$branchArgument, $url, 'dbt-project'], $this->dataDir); @@ -121,4 +108,27 @@ public function getCurrentBranch(string $projectPath): array 'ref' => trim($process->getOutput()), ]; } + + /** + * @throws \Keboola\Component\UserException + */ + public function getUrl(string $repositoryUrl, ?string $username = null, ?string $password = null): string + { + $parsedUrl = parse_url($repositoryUrl); + if (!$parsedUrl || !array_key_exists('host', $parsedUrl)) { + throw new UserException(sprintf('Wrong URL format "%s"', $repositoryUrl)); + } + if ($username && $password) { + $url = (string) str_replace($parsedUrl['host'], sprintf( + '%s:%s@%s', + urlencode($username), + urlencode($password), + $parsedUrl['host'] + ), $repositoryUrl); + } else { + $url = $repositoryUrl; + } + + return $url; + } } diff --git a/tests/phpunit/Service/GitRepositoryServiceTest.php b/tests/phpunit/Service/GitRepositoryServiceTest.php index 3f220b64..90443b5a 100644 --- a/tests/phpunit/Service/GitRepositoryServiceTest.php +++ b/tests/phpunit/Service/GitRepositoryServiceTest.php @@ -79,6 +79,27 @@ public function testListBranchesEmptyGitProject(): void self::assertEmpty($branches); } + /** + * @dataProvider getUrlValidParameters + */ + public function testGetRepositoryUrl( + string $url, + ?string $username, + ?string $password, + string $expectedUrl + ): void { + $gitService = new GitRepositoryService($this->dataDir); + self::assertSame($expectedUrl, $gitService->getUrl($url, $username, $password)); + } + + public function testGetInvalidRepositoryUrl(): void + { + $this->expectException(UserException::class); + $this->expectExceptionMessage('Wrong URL format "invalid url"'); + $gitService = new GitRepositoryService($this->dataDir); + $gitService->getUrl('invalid url'); + } + /** * @dataProvider privateRepositoryInvalidCredentials */ @@ -156,4 +177,33 @@ public function privateRepositoryInvalidCredentials(): Generator 'errorMsg' => 'Wrong URL format "some random string"', ]; } + + public function getUrlValidParameters(): Generator + { + yield 'public repository' => [ + 'url' => 'https://github.com/keboola/dbt-test-project-public', + 'username' => null, + 'password' => null, + 'expectedUrl' => 'https://github.com/keboola/dbt-test-project-public', + ]; + + yield 'private repository' => [ + 'url' => 'https://github.com/keboola/dbt-test-project.git', + 'username' => getenv('GITHUB_USERNAME') ?: '', + 'password' => getenv('GITHUB_PASSWORD') ?: '', + 'expectedUrl' => sprintf( + 'https://%s:%s@%s', + getenv('GITHUB_USERNAME') ?: '', + getenv('GITHUB_PASSWORD') ?: '', + 'github.com/keboola/dbt-test-project.git', + ), + ]; + + yield 'private repository with special chars' => [ + 'url' => 'https://github.com/keboola/dbt-test-project.git', + 'username' => 'user@company.com', + 'password' => '/some@password!', + 'expectedUrl' => 'https://user%40company.com:%2Fsome%40password%21@github.com/keboola/dbt-test-project.git', + ]; + } }