mirror of
https://github.com/shlinkio/shlink.git
synced 2026-02-28 04:03:12 +08:00
Allowed to set redirects for default domain via command line or API
This commit is contained in:
@@ -99,16 +99,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"403": {
|
|
||||||
"description": "Default domain was provided, and it cannot be edited this way.",
|
|
||||||
"content": {
|
|
||||||
"application/problem+json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "../definitions/Error.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Unexpected error.",
|
"description": "Unexpected error.",
|
||||||
"content": {
|
"content": {
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
|||||||
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Core\Entity\Domain;
|
use Shlinkio\Shlink\Core\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Exception\InvalidDomainException;
|
|
||||||
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
use function Functional\first;
|
||||||
|
use function Functional\group;
|
||||||
use function Functional\map;
|
use function Functional\map;
|
||||||
|
|
||||||
class DomainService implements DomainServiceInterface
|
class DomainService implements DomainServiceInterface
|
||||||
@@ -31,9 +32,7 @@ class DomainService implements DomainServiceInterface
|
|||||||
*/
|
*/
|
||||||
public function listDomains(?ApiKey $apiKey = null): array
|
public function listDomains(?ApiKey $apiKey = null): array
|
||||||
{
|
{
|
||||||
/** @var DomainRepositoryInterface $repo */
|
[$default, $domains] = $this->defaultDomainAndRest($apiKey);
|
||||||
$repo = $this->em->getRepository(Domain::class);
|
|
||||||
$domains = $repo->findDomainsWithout($this->defaultDomain, $apiKey);
|
|
||||||
$mappedDomains = map($domains, fn (Domain $domain) => DomainItem::forExistingDomain($domain));
|
$mappedDomains = map($domains, fn (Domain $domain) => DomainItem::forExistingDomain($domain));
|
||||||
|
|
||||||
if ($apiKey?->hasRole(Role::DOMAIN_SPECIFIC)) {
|
if ($apiKey?->hasRole(Role::DOMAIN_SPECIFIC)) {
|
||||||
@@ -41,11 +40,26 @@ class DomainService implements DomainServiceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
DomainItem::forDefaultDomain($this->defaultDomain, $this->redirectOptions),
|
DomainItem::forDefaultDomain($this->defaultDomain, $default ?? $this->redirectOptions),
|
||||||
...$mappedDomains,
|
...$mappedDomains,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{Domain|null, Domain[]}
|
||||||
|
*/
|
||||||
|
private function defaultDomainAndRest(?ApiKey $apiKey): array
|
||||||
|
{
|
||||||
|
/** @var DomainRepositoryInterface $repo */
|
||||||
|
$repo = $this->em->getRepository(Domain::class);
|
||||||
|
$groups = group(
|
||||||
|
$repo->findDomainsWithout(null, $apiKey), // FIXME Always called with null as first arg
|
||||||
|
fn (Domain $domain) => $domain->getAuthority() === $this->defaultDomain ? 'default' : 'domains',
|
||||||
|
);
|
||||||
|
|
||||||
|
return [first($groups['default'] ?? []), $groups['domains'] ?? []];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws DomainNotFoundException
|
* @throws DomainNotFoundException
|
||||||
*/
|
*/
|
||||||
@@ -79,17 +93,12 @@ class DomainService implements DomainServiceInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws DomainNotFoundException
|
* @throws DomainNotFoundException
|
||||||
* @throws InvalidDomainException
|
|
||||||
*/
|
*/
|
||||||
public function configureNotFoundRedirects(
|
public function configureNotFoundRedirects(
|
||||||
string $authority,
|
string $authority,
|
||||||
NotFoundRedirects $notFoundRedirects,
|
NotFoundRedirects $notFoundRedirects,
|
||||||
?ApiKey $apiKey = null,
|
?ApiKey $apiKey = null,
|
||||||
): Domain {
|
): Domain {
|
||||||
if ($authority === $this->defaultDomain) {
|
|
||||||
throw InvalidDomainException::forDefaultDomainRedirects();
|
|
||||||
}
|
|
||||||
|
|
||||||
$domain = $this->getPersistedDomain($authority, $apiKey);
|
$domain = $this->getPersistedDomain($authority, $apiKey);
|
||||||
$domain->configureNotFoundRedirects($notFoundRedirects);
|
$domain->configureNotFoundRedirects($notFoundRedirects);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
|
|||||||
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
||||||
use Shlinkio\Shlink\Core\Entity\Domain;
|
use Shlinkio\Shlink\Core\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Exception\InvalidDomainException;
|
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
interface DomainServiceInterface
|
interface DomainServiceInterface
|
||||||
@@ -32,7 +31,6 @@ interface DomainServiceInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws DomainNotFoundException If the API key is restricted to one domain and a different one is provided
|
* @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(
|
public function configureNotFoundRedirects(
|
||||||
string $authority,
|
string $authority,
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\Exception;
|
|
||||||
|
|
||||||
use Fig\Http\Message\StatusCodeInterface;
|
|
||||||
use Mezzio\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
|
|
||||||
use Mezzio\ProblemDetails\Exception\ProblemDetailsExceptionInterface;
|
|
||||||
|
|
||||||
class InvalidDomainException extends DomainException implements ProblemDetailsExceptionInterface
|
|
||||||
{
|
|
||||||
use CommonProblemDetailsExceptionTrait;
|
|
||||||
|
|
||||||
private const TITLE = 'Invalid domain';
|
|
||||||
private const TYPE = 'INVALID_DOMAIN';
|
|
||||||
|
|
||||||
private function __construct(string $message)
|
|
||||||
{
|
|
||||||
parent::__construct($message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function forDefaultDomainRedirects(): self
|
|
||||||
{
|
|
||||||
$e = new self('You cannot configure default domain\'s redirects this way. Use the configuration or env vars.');
|
|
||||||
$e->detail = $e->getMessage();
|
|
||||||
$e->title = self::TITLE;
|
|
||||||
$e->type = self::TYPE;
|
|
||||||
$e->status = StatusCodeInterface::STATUS_FORBIDDEN;
|
|
||||||
|
|
||||||
return $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@ use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
|||||||
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Core\Entity\Domain;
|
use Shlinkio\Shlink\Core\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\DomainNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Exception\InvalidDomainException;
|
|
||||||
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
|
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
|
||||||
@@ -42,7 +41,7 @@ class DomainServiceTest extends TestCase
|
|||||||
{
|
{
|
||||||
$repo = $this->prophesize(DomainRepositoryInterface::class);
|
$repo = $this->prophesize(DomainRepositoryInterface::class);
|
||||||
$getRepo = $this->em->getRepository(Domain::class)->willReturn($repo->reveal());
|
$getRepo = $this->em->getRepository(Domain::class)->willReturn($repo->reveal());
|
||||||
$findDomains = $repo->findDomainsWithout('default.com', $apiKey)->willReturn($domains);
|
$findDomains = $repo->findDomainsWithout(null, $apiKey)->willReturn($domains);
|
||||||
|
|
||||||
$result = $this->domainService->listDomains($apiKey);
|
$result = $this->domainService->listDomains($apiKey);
|
||||||
|
|
||||||
@@ -214,15 +213,4 @@ class DomainServiceTest extends TestCase
|
|||||||
yield 'domain not found and author API key' => [null, $authorApiKey];
|
yield 'domain not found and author API key' => [null, $authorApiKey];
|
||||||
yield 'domain found and author API key' => [$domain, $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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace ShlinkioTest\Shlink\Core\Exception;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use Shlinkio\Shlink\Core\Exception\InvalidDomainException;
|
|
||||||
|
|
||||||
class InvalidDomainExceptionTest extends TestCase
|
|
||||||
{
|
|
||||||
/** @test */
|
|
||||||
public function configuresTheExceptionAsExpected(): void
|
|
||||||
{
|
|
||||||
$e = InvalidDomainException::forDefaultDomainRedirects();
|
|
||||||
$expected = 'You cannot configure default domain\'s redirects this way. Use the configuration or env vars.';
|
|
||||||
|
|
||||||
self::assertEquals($expected, $e->getMessage());
|
|
||||||
self::assertEquals($expected, $e->getDetail());
|
|
||||||
self::assertEquals('Invalid domain', $e->getTitle());
|
|
||||||
self::assertEquals('INVALID_DOMAIN', $e->getType());
|
|
||||||
self::assertEquals(403, $e->getStatus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user