diff --git a/CHANGELOG.md b/CHANGELOG.md index 374dde6a..74082f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this * *Nothing* +## [3.0.3] - 2022-02-19 +### Added +* *Nothing* + +### Changed +* [#1382](https://github.com/shlinkio/shlink/issues/1382) Updated docker image to PHP 8.1.3. + +### Deprecated +* *Nothing* + +### Removed +* *Nothing* + +### Fixed +* [#1377](https://github.com/shlinkio/shlink/issues/1377) Fixed installer always setting delete threshold with value 1. +* [#1379](https://github.com/shlinkio/shlink/issues/1379) Ensured API keys cannot be created with a domain-only role linked to default domain. + + ## [3.0.2] - 2022-02-10 ### Added * *Nothing* diff --git a/Dockerfile b/Dockerfile index 8ee2ffa9..1d07fd34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1.1-alpine3.15 as base +FROM php:8.1.3-alpine3.15 as base ARG SHLINK_VERSION=latest ENV SHLINK_VERSION ${SHLINK_VERSION} diff --git a/composer.json b/composer.json index 52ba9c87..abcb6442 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "shlinkio/shlink-config": "^1.6", "shlinkio/shlink-event-dispatcher": "^2.3", "shlinkio/shlink-importer": "^2.5", - "shlinkio/shlink-installer": "dev-develop#68f5de1 as 7.1", + "shlinkio/shlink-installer": "dev-develop#ea5e967 as 7.1", "shlinkio/shlink-ip-geolocation": "^2.2", "symfony/console": "^6.0", "symfony/filesystem": "^6.0", diff --git a/data/infra/php.Dockerfile b/data/infra/php.Dockerfile index ee34034d..474e4253 100644 --- a/data/infra/php.Dockerfile +++ b/data/infra/php.Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1.1-fpm-alpine3.15 +FROM php:8.1.3-fpm-alpine3.15 MAINTAINER Alejandro Celaya ENV APCU_VERSION 5.1.21 diff --git a/data/infra/swoole.Dockerfile b/data/infra/swoole.Dockerfile index 24655a4f..cc004dbe 100644 --- a/data/infra/swoole.Dockerfile +++ b/data/infra/swoole.Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1.1-alpine3.15 +FROM php:8.1.3-alpine3.15 MAINTAINER Alejandro Celaya ENV APCU_VERSION 5.1.21 diff --git a/module/CLI/config/dependencies.config.php b/module/CLI/config/dependencies.config.php index da23b0f6..137bdd7a 100644 --- a/module/CLI/config/dependencies.config.php +++ b/module/CLI/config/dependencies.config.php @@ -72,7 +72,7 @@ return [ TrackingOptions::class, ], Util\ProcessRunner::class => [SymfonyCli\Helper\ProcessHelper::class], - ApiKey\RoleResolver::class => [DomainService::class], + ApiKey\RoleResolver::class => [DomainService::class, 'config.url_shortener.domain.hostname'], Command\ShortUrl\CreateShortUrlCommand::class => [ Service\UrlShortener::class, diff --git a/module/CLI/src/ApiKey/RoleResolver.php b/module/CLI/src/ApiKey/RoleResolver.php index c8cccfc6..588a2fa2 100644 --- a/module/CLI/src/ApiKey/RoleResolver.php +++ b/module/CLI/src/ApiKey/RoleResolver.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\ApiKey; +use Shlinkio\Shlink\CLI\Exception\InvalidRoleConfigException; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; use Symfony\Component\Console\Input\InputInterface; @@ -12,24 +13,33 @@ use function is_string; class RoleResolver implements RoleResolverInterface { - public function __construct(private DomainServiceInterface $domainService) + public function __construct(private DomainServiceInterface $domainService, private string $defaultDomain) { } public function determineRoles(InputInterface $input): array { - $domainAuthority = $input->getOption('domain-only'); - $author = $input->getOption('author-only'); + $domainAuthority = $input->getOption(self::DOMAIN_ONLY_PARAM); + $author = $input->getOption(self::AUTHOR_ONLY_PARAM); $roleDefinitions = []; if ($author) { $roleDefinitions[] = RoleDefinition::forAuthoredShortUrls(); } if (is_string($domainAuthority)) { - $domain = $this->domainService->getOrCreate($domainAuthority); - $roleDefinitions[] = RoleDefinition::forDomain($domain); + $roleDefinitions[] = $this->resolveRoleForAuthority($domainAuthority); } return $roleDefinitions; } + + private function resolveRoleForAuthority(string $domainAuthority): RoleDefinition + { + if ($domainAuthority === $this->defaultDomain) { + throw InvalidRoleConfigException::forDomainOnlyWithDefaultDomain(); + } + + $domain = $this->domainService->getOrCreate($domainAuthority); + return RoleDefinition::forDomain($domain); + } } diff --git a/module/CLI/src/Exception/InvalidRoleConfigException.php b/module/CLI/src/Exception/InvalidRoleConfigException.php new file mode 100644 index 00000000..51adb234 --- /dev/null +++ b/module/CLI/src/Exception/InvalidRoleConfigException.php @@ -0,0 +1,22 @@ +domainService = $this->prophesize(DomainServiceInterface::class); - $this->resolver = new RoleResolver($this->domainService->reveal()); + $this->resolver = new RoleResolver($this->domainService->reveal(), 'default.com'); } /** @@ -94,4 +95,16 @@ class RoleResolverTest extends TestCase 1, ]; } + + /** @test */ + public function exceptionIsThrownWhenTryingToAddDomainOnlyLinkedToDefaultDomain(): void + { + $input = $this->prophesize(InputInterface::class); + $input->getOption(RoleResolver::DOMAIN_ONLY_PARAM)->willReturn('default.com'); + $input->getOption(RoleResolver::AUTHOR_ONLY_PARAM)->willReturn(null); + + $this->expectException(InvalidRoleConfigException::class); + + $this->resolver->determineRoles($input->reveal()); + } } diff --git a/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php b/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php new file mode 100644 index 00000000..3b89b505 --- /dev/null +++ b/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php @@ -0,0 +1,26 @@ +getMessage()); + } +}