From 7c06633a678f76e3a2ec17aeb8865f8350a7b2f3 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Tue, 3 Aug 2021 18:28:04 +0200 Subject: [PATCH] Ensured default domain redirects cannot be edited through regular approach --- module/Core/src/Domain/DomainService.php | 6 ++++ .../src/Domain/DomainServiceInterface.php | 2 ++ .../src/Exception/InvalidDomainException.php | 33 +++++++++++++++++++ module/Core/test/Domain/DomainServiceTest.php | 12 +++++++ .../Exception/InvalidDomainExceptionTest.php | 24 ++++++++++++++ .../Action/Domain/DomainRedirectsAction.php | 2 -- 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 module/Core/src/Exception/InvalidDomainException.php create mode 100644 module/Core/test/Exception/InvalidDomainExceptionTest.php diff --git a/module/Core/src/Domain/DomainService.php b/module/Core/src/Domain/DomainService.php index 807c6dce..6051c254 100644 --- a/module/Core/src/Domain/DomainService.php +++ b/module/Core/src/Domain/DomainService.php @@ -10,6 +10,7 @@ use Shlinkio\Shlink\Core\Domain\Model\DomainItem; use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface; use Shlinkio\Shlink\Core\Entity\Domain; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; +use Shlinkio\Shlink\Core\Exception\InvalidDomainException; use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions; use Shlinkio\Shlink\Rest\ApiKey\Role; use Shlinkio\Shlink\Rest\Entity\ApiKey; @@ -78,12 +79,17 @@ class DomainService implements DomainServiceInterface /** * @throws DomainNotFoundException + * @throws InvalidDomainException */ public function configureNotFoundRedirects( string $authority, NotFoundRedirects $notFoundRedirects, ?ApiKey $apiKey = null ): Domain { + if ($authority === $this->defaultDomain) { + throw InvalidDomainException::forDefaultDomainRedirects(); + } + $domain = $this->getPersistedDomain($authority, $apiKey); $domain->configureNotFoundRedirects($notFoundRedirects); diff --git a/module/Core/src/Domain/DomainServiceInterface.php b/module/Core/src/Domain/DomainServiceInterface.php index 9ac48e69..7748284d 100644 --- a/module/Core/src/Domain/DomainServiceInterface.php +++ b/module/Core/src/Domain/DomainServiceInterface.php @@ -8,6 +8,7 @@ use Shlinkio\Shlink\Core\Config\NotFoundRedirects; use Shlinkio\Shlink\Core\Domain\Model\DomainItem; use Shlinkio\Shlink\Core\Entity\Domain; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; +use Shlinkio\Shlink\Core\Exception\InvalidDomainException; use Shlinkio\Shlink\Rest\Entity\ApiKey; interface DomainServiceInterface @@ -31,6 +32,7 @@ interface DomainServiceInterface /** * @throws DomainNotFoundException If the API key is restricted to one domain and a different one is provided + * @throws InvalidDomainException If default domain is provided */ public function configureNotFoundRedirects( string $authority, diff --git a/module/Core/src/Exception/InvalidDomainException.php b/module/Core/src/Exception/InvalidDomainException.php new file mode 100644 index 00000000..6e71c831 --- /dev/null +++ b/module/Core/src/Exception/InvalidDomainException.php @@ -0,0 +1,33 @@ +detail = $e->getMessage(); + $e->title = self::TITLE; + $e->type = self::TYPE; + $e->status = StatusCodeInterface::STATUS_BAD_REQUEST; + + return $e; + } +} diff --git a/module/Core/test/Domain/DomainServiceTest.php b/module/Core/test/Domain/DomainServiceTest.php index 812210dd..159fb6ca 100644 --- a/module/Core/test/Domain/DomainServiceTest.php +++ b/module/Core/test/Domain/DomainServiceTest.php @@ -15,6 +15,7 @@ use Shlinkio\Shlink\Core\Domain\Model\DomainItem; use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface; use Shlinkio\Shlink\Core\Entity\Domain; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; +use Shlinkio\Shlink\Core\Exception\InvalidDomainException; use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions; use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; @@ -213,4 +214,15 @@ class DomainServiceTest extends TestCase yield 'domain not found and author API key' => [null, $authorApiKey]; yield 'domain found and author API key' => [$domain, $authorApiKey]; } + + /** @test */ + public function anExceptionIsThrowsWhenTryingToEditRedirectsForDefaultDomain(): void + { + $this->expectException(InvalidDomainException::class); + $this->expectExceptionMessage( + 'You cannot configure default domain\'s redirects this way. Use the configuration or env vars.', + ); + + $this->domainService->configureNotFoundRedirects('default.com', NotFoundRedirects::withoutRedirects()); + } } diff --git a/module/Core/test/Exception/InvalidDomainExceptionTest.php b/module/Core/test/Exception/InvalidDomainExceptionTest.php new file mode 100644 index 00000000..e4592cd8 --- /dev/null +++ b/module/Core/test/Exception/InvalidDomainExceptionTest.php @@ -0,0 +1,24 @@ +getMessage()); + self::assertEquals($expected, $e->getDetail()); + self::assertEquals('Invalid domain', $e->getTitle()); + self::assertEquals('INVALID_DOMAIN', $e->getType()); + self::assertEquals(400, $e->getStatus()); + } +} diff --git a/module/Rest/src/Action/Domain/DomainRedirectsAction.php b/module/Rest/src/Action/Domain/DomainRedirectsAction.php index ca4346f8..e98aa339 100644 --- a/module/Rest/src/Action/Domain/DomainRedirectsAction.php +++ b/module/Rest/src/Action/Domain/DomainRedirectsAction.php @@ -23,8 +23,6 @@ class DomainRedirectsAction extends AbstractRestAction public function handle(ServerRequestInterface $request): ResponseInterface { - // TODO Do not allow to set redirects for default domain. Or do allow. Check if there could be any issue - /** @var array $body */ $body = $request->getParsedBody(); $requestData = DomainRedirectsRequest::fromRawData($body);