Fixed merge conflicts

This commit is contained in:
Alejandro Celaya 2022-02-19 19:47:34 +01:00
commit c52f3c396b
10 changed files with 100 additions and 11 deletions

View file

@ -21,6 +21,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
* *Nothing* * *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 ## [3.0.2] - 2022-02-10
### Added ### Added
* *Nothing* * *Nothing*

View file

@ -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 ARG SHLINK_VERSION=latest
ENV SHLINK_VERSION ${SHLINK_VERSION} ENV SHLINK_VERSION ${SHLINK_VERSION}

View file

@ -51,7 +51,7 @@
"shlinkio/shlink-config": "^1.6", "shlinkio/shlink-config": "^1.6",
"shlinkio/shlink-event-dispatcher": "^2.3", "shlinkio/shlink-event-dispatcher": "^2.3",
"shlinkio/shlink-importer": "^2.5", "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", "shlinkio/shlink-ip-geolocation": "^2.2",
"symfony/console": "^6.0", "symfony/console": "^6.0",
"symfony/filesystem": "^6.0", "symfony/filesystem": "^6.0",

View file

@ -1,4 +1,4 @@
FROM php:8.1.1-fpm-alpine3.15 FROM php:8.1.3-fpm-alpine3.15
MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com> MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com>
ENV APCU_VERSION 5.1.21 ENV APCU_VERSION 5.1.21

View file

@ -1,4 +1,4 @@
FROM php:8.1.1-alpine3.15 FROM php:8.1.3-alpine3.15
MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com> MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com>
ENV APCU_VERSION 5.1.21 ENV APCU_VERSION 5.1.21

View file

@ -72,7 +72,7 @@ return [
TrackingOptions::class, TrackingOptions::class,
], ],
Util\ProcessRunner::class => [SymfonyCli\Helper\ProcessHelper::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 => [ Command\ShortUrl\CreateShortUrlCommand::class => [
Service\UrlShortener::class, Service\UrlShortener::class,

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\ApiKey; namespace Shlinkio\Shlink\CLI\ApiKey;
use Shlinkio\Shlink\CLI\Exception\InvalidRoleConfigException;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -12,24 +13,33 @@ use function is_string;
class RoleResolver implements RoleResolverInterface 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 public function determineRoles(InputInterface $input): array
{ {
$domainAuthority = $input->getOption('domain-only'); $domainAuthority = $input->getOption(self::DOMAIN_ONLY_PARAM);
$author = $input->getOption('author-only'); $author = $input->getOption(self::AUTHOR_ONLY_PARAM);
$roleDefinitions = []; $roleDefinitions = [];
if ($author) { if ($author) {
$roleDefinitions[] = RoleDefinition::forAuthoredShortUrls(); $roleDefinitions[] = RoleDefinition::forAuthoredShortUrls();
} }
if (is_string($domainAuthority)) { if (is_string($domainAuthority)) {
$domain = $this->domainService->getOrCreate($domainAuthority); $roleDefinitions[] = $this->resolveRoleForAuthority($domainAuthority);
$roleDefinitions[] = RoleDefinition::forDomain($domain);
} }
return $roleDefinitions; return $roleDefinitions;
} }
private function resolveRoleForAuthority(string $domainAuthority): RoleDefinition
{
if ($domainAuthority === $this->defaultDomain) {
throw InvalidRoleConfigException::forDomainOnlyWithDefaultDomain();
}
$domain = $this->domainService->getOrCreate($domainAuthority);
return RoleDefinition::forDomain($domain);
}
} }

View file

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Exception;
use InvalidArgumentException;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use function sprintf;
class InvalidRoleConfigException extends InvalidArgumentException implements ExceptionInterface
{
public static function forDomainOnlyWithDefaultDomain(): self
{
return new self(sprintf(
'You cannot create an API key with the "%s" role attached to the default domain. '
. 'The role is currently limited to non-default domains.',
Role::DOMAIN_SPECIFIC,
));
}
}

View file

@ -8,6 +8,7 @@ use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\ApiKey\RoleResolver; use Shlinkio\Shlink\CLI\ApiKey\RoleResolver;
use Shlinkio\Shlink\CLI\Exception\InvalidRoleConfigException;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Entity\Domain; use Shlinkio\Shlink\Core\Entity\Domain;
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
@ -23,7 +24,7 @@ class RoleResolverTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->domainService = $this->prophesize(DomainServiceInterface::class); $this->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, 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());
}
} }

View file

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Exception;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Exception\InvalidRoleConfigException;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use function sprintf;
class InvalidRoleConfigExceptionTest extends TestCase
{
/** @test */
public function forDomainOnlyWithDefaultDomainGeneratesExpectedException(): void
{
$e = InvalidRoleConfigException::forDomainOnlyWithDefaultDomain();
self::assertEquals(sprintf(
'You cannot create an API key with the "%s" role attached to the default domain. '
. 'The role is currently limited to non-default domains.',
Role::DOMAIN_SPECIFIC,
), $e->getMessage());
}
}