Enhanced ListDomainsAction so that it returns default redirects in the response

This commit is contained in:
Alejandro Celaya 2021-12-09 12:11:09 +01:00
parent 0b22fb933c
commit 348ac78f5a
7 changed files with 43 additions and 25 deletions

View File

@ -46,6 +46,9 @@
} }
} }
} }
},
"defaultRedirects": {
"$ref": "../definitions/NotFoundRedirects.json"
} }
} }
} }
@ -84,7 +87,12 @@
"invalidShortUrlRedirect": "https://example.com/invalid-url" "invalidShortUrlRedirect": "https://example.com/invalid-url"
} }
} }
] ],
"defaultRedirects": {
"baseUrlRedirect": "https://somewhere.com",
"regular404Redirect": null,
"invalidShortUrlRedirect": null
}
} }
} }
} }

View File

@ -4,10 +4,11 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Options; namespace Shlinkio\Shlink\Core\Options;
use JsonSerializable;
use Laminas\Stdlib\AbstractOptions; use Laminas\Stdlib\AbstractOptions;
use Shlinkio\Shlink\Core\Config\NotFoundRedirectConfigInterface; use Shlinkio\Shlink\Core\Config\NotFoundRedirectConfigInterface;
class NotFoundRedirectOptions extends AbstractOptions implements NotFoundRedirectConfigInterface class NotFoundRedirectOptions extends AbstractOptions implements NotFoundRedirectConfigInterface, JsonSerializable
{ {
private ?string $invalidShortUrl = null; private ?string $invalidShortUrl = null;
private ?string $regular404 = null; private ?string $regular404 = null;
@ -60,4 +61,13 @@ class NotFoundRedirectOptions extends AbstractOptions implements NotFoundRedirec
$this->baseUrl = $baseUrl; $this->baseUrl = $baseUrl;
return $this; return $this;
} }
public function jsonSerialize(): array
{
return [
'baseUrlRedirect' => $this->baseUrl,
'regular404Redirect' => $this->regular404,
'invalidShortUrlRedirect' => $this->invalidShortUrl,
];
}
} }

View File

@ -9,7 +9,7 @@ use Laminas\ServiceManager\Factory\InvokableFactory;
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware; use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider; use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider;
use Shlinkio\Shlink\Core\Domain\DomainService; use Shlinkio\Shlink\Core\Domain\DomainService;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options;
use Shlinkio\Shlink\Core\Service; use Shlinkio\Shlink\Core\Service;
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer; use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer;
use Shlinkio\Shlink\Core\Tag\TagService; use Shlinkio\Shlink\Core\Tag\TagService;
@ -55,7 +55,7 @@ return [
ConfigAbstractFactory::class => [ ConfigAbstractFactory::class => [
ApiKeyService::class => ['em'], ApiKeyService::class => ['em'],
Action\HealthAction::class => ['em', AppOptions::class], Action\HealthAction::class => ['em', Options\AppOptions::class],
Action\MercureInfoAction::class => [LcobucciJwtProvider::class, 'config.mercure'], Action\MercureInfoAction::class => [LcobucciJwtProvider::class, 'config.mercure'],
Action\ShortUrl\CreateShortUrlAction::class => [Service\UrlShortener::class, ShortUrlDataTransformer::class], Action\ShortUrl\CreateShortUrlAction::class => [Service\UrlShortener::class, ShortUrlDataTransformer::class],
Action\ShortUrl\SingleStepCreateShortUrlAction::class => [ Action\ShortUrl\SingleStepCreateShortUrlAction::class => [
@ -81,7 +81,7 @@ return [
Action\Tag\DeleteTagsAction::class => [TagService::class], Action\Tag\DeleteTagsAction::class => [TagService::class],
Action\Tag\CreateTagsAction::class => [TagService::class], Action\Tag\CreateTagsAction::class => [TagService::class],
Action\Tag\UpdateTagAction::class => [TagService::class], Action\Tag\UpdateTagAction::class => [TagService::class],
Action\Domain\ListDomainsAction::class => [DomainService::class], Action\Domain\ListDomainsAction::class => [DomainService::class, Options\NotFoundRedirectOptions::class],
Action\Domain\DomainRedirectsAction::class => [DomainService::class], Action\Domain\DomainRedirectsAction::class => [DomainService::class],
Middleware\CrossDomainMiddleware::class => ['config.cors'], Middleware\CrossDomainMiddleware::class => ['config.cors'],

View File

@ -8,6 +8,7 @@ use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
@ -16,7 +17,7 @@ class ListDomainsAction extends AbstractRestAction
protected const ROUTE_PATH = '/domains'; protected const ROUTE_PATH = '/domains';
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
public function __construct(private DomainServiceInterface $domainService) public function __construct(private DomainServiceInterface $domainService, private NotFoundRedirectOptions $options)
{ {
} }
@ -28,6 +29,7 @@ class ListDomainsAction extends AbstractRestAction
return new JsonResponse([ return new JsonResponse([
'domains' => [ 'domains' => [
'data' => $domainItems, 'data' => $domainItems,
'defaultRedirects' => $this->options,
], ],
]); ]);
} }

View File

@ -9,24 +9,6 @@ use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
class DomainRedirectsTest extends ApiTestCase class DomainRedirectsTest extends ApiTestCase
{ {
/** @test */
public function anErrorIsReturnedWhenTryingToEditDefaultDomain(): void
{
$resp = $this->callApiWithKey(self::METHOD_PATCH, '/domains/redirects', [
RequestOptions::JSON => ['domain' => 'doma.in'],
]);
$payload = $this->getJsonResponsePayload($resp);
self::assertEquals(self::STATUS_FORBIDDEN, $resp->getStatusCode());
self::assertEquals(self::STATUS_FORBIDDEN, $payload['status']);
self::assertEquals('INVALID_DOMAIN', $payload['type']);
self::assertEquals(
'You cannot configure default domain\'s redirects this way. Use the configuration or env vars.',
$payload['detail'],
);
self::assertEquals('Invalid domain', $payload['title']);
}
/** /**
* @test * @test
* @dataProvider provideInvalidDomains * @dataProvider provideInvalidDomains
@ -78,6 +60,14 @@ class DomainRedirectsTest extends ApiTestCase
'regular404Redirect' => 'foo.com', 'regular404Redirect' => 'foo.com',
'invalidShortUrlRedirect' => null, 'invalidShortUrlRedirect' => null,
]]; ]];
yield 'default domain' => [[
'domain' => 'doma.in',
'regular404Redirect' => 'foo-for-default.com',
], [
'baseUrlRedirect' => null,
'regular404Redirect' => 'foo-for-default.com',
'invalidShortUrlRedirect' => null,
]];
yield 'existing domain with redirects' => [[ yield 'existing domain with redirects' => [[
'domain' => 'detached-with-redirects.com', 'domain' => 'detached-with-redirects.com',
'baseUrlRedirect' => null, 'baseUrlRedirect' => null,

View File

@ -21,6 +21,11 @@ class ListDomainsTest extends ApiTestCase
self::assertEquals([ self::assertEquals([
'domains' => [ 'domains' => [
'data' => $expectedDomains, 'data' => $expectedDomains,
'defaultRedirects' => [
'baseUrlRedirect' => null,
'regular404Redirect' => null,
'invalidShortUrlRedirect' => null,
],
], ],
], $respPayload); ], $respPayload);
} }

View File

@ -22,11 +22,13 @@ class ListDomainsActionTest extends TestCase
private ListDomainsAction $action; private ListDomainsAction $action;
private ObjectProphecy $domainService; private ObjectProphecy $domainService;
private NotFoundRedirectOptions $options;
public function setUp(): void public function setUp(): void
{ {
$this->domainService = $this->prophesize(DomainServiceInterface::class); $this->domainService = $this->prophesize(DomainServiceInterface::class);
$this->action = new ListDomainsAction($this->domainService->reveal()); $this->options = new NotFoundRedirectOptions();
$this->action = new ListDomainsAction($this->domainService->reveal(), $this->options);
} }
/** @test */ /** @test */
@ -46,6 +48,7 @@ class ListDomainsActionTest extends TestCase
self::assertEquals([ self::assertEquals([
'domains' => [ 'domains' => [
'data' => $domains, 'data' => $domains,
'defaultRedirects' => $this->options,
], ],
], $payload); ], $payload);
$listDomains->shouldHaveBeenCalledOnce(); $listDomains->shouldHaveBeenCalledOnce();