Deleted everything related with authentication plugins, as shlink only supports API key auth since v2.0.0

This commit is contained in:
Alejandro Celaya 2020-11-07 12:53:14 +01:00
parent 098751d256
commit d6395a3de8
17 changed files with 100 additions and 453 deletions

View File

@ -14,37 +14,16 @@ return [
Action\ShortUrl\SingleStepCreateShortUrlAction::class,
ConfigProvider::UNVERSIONED_HEALTH_ENDPOINT_NAME,
],
'plugins' => [
'factories' => [
Authentication\Plugin\ApiKeyHeaderPlugin::class => ConfigAbstractFactory::class,
],
'aliases' => [
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME =>
Authentication\Plugin\ApiKeyHeaderPlugin::class,
],
],
],
'dependencies' => [
'factories' => [
Authentication\AuthenticationPluginManager::class =>
Authentication\AuthenticationPluginManagerFactory::class,
Authentication\RequestToHttpAuthPlugin::class => ConfigAbstractFactory::class,
Middleware\AuthenticationMiddleware::class => ConfigAbstractFactory::class,
],
],
ConfigAbstractFactory::class => [
Authentication\Plugin\ApiKeyHeaderPlugin::class => [Service\ApiKeyService::class],
Authentication\RequestToHttpAuthPlugin::class => [Authentication\AuthenticationPluginManager::class],
Middleware\AuthenticationMiddleware::class => [
Authentication\RequestToHttpAuthPlugin::class,
'config.auth.routes_whitelist',
],
Middleware\AuthenticationMiddleware::class => [Service\ApiKeyService::class, 'config.auth.routes_whitelist'],
],
];

View File

@ -9,7 +9,7 @@ use Shlinkio\Shlink\Core\Exception\ValidationException;
use Shlinkio\Shlink\Core\Model\CreateShortUrlData;
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter;
use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
class CreateShortUrlAction extends AbstractCreateShortUrlAction
{
@ -28,7 +28,7 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
]);
}
$payload[ShortUrlMetaInputFilter::API_KEY] = $request->getHeaderLine(ApiKeyHeaderPlugin::HEADER_NAME);
$payload[ShortUrlMetaInputFilter::API_KEY] = AuthenticationMiddleware::apiKeyFromRequest($request);
$meta = ShortUrlMeta::fromRawData($payload);
return new CreateShortUrlData($payload['longUrl'], (array) ($payload['tags'] ?? []), $meta);

View File

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication;
use Laminas\ServiceManager\AbstractPluginManager;
class AuthenticationPluginManager extends AbstractPluginManager implements AuthenticationPluginManagerInterface
{
protected $instanceOf = Plugin\AuthenticationPluginInterface::class; // phpcs:ignore
}

View File

@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication;
use Psr\Container\ContainerInterface;
class AuthenticationPluginManagerFactory
{
public function __invoke(ContainerInterface $container): AuthenticationPluginManager
{
$config = $container->has('config') ? $container->get('config') : [];
return new AuthenticationPluginManager($container, $config['auth']['plugins'] ?? []);
}
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication;
use Psr\Container\ContainerInterface;
interface AuthenticationPluginManagerInterface extends ContainerInterface
{
}

View File

@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication\Plugin;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
class ApiKeyHeaderPlugin implements AuthenticationPluginInterface
{
public const HEADER_NAME = 'X-Api-Key';
private ApiKeyServiceInterface $apiKeyService;
public function __construct(ApiKeyServiceInterface $apiKeyService)
{
$this->apiKeyService = $apiKeyService;
}
/**
* @throws VerifyAuthenticationException
*/
public function verify(ServerRequestInterface $request): void
{
$apiKey = $request->getHeaderLine(self::HEADER_NAME);
if (! $this->apiKeyService->check($apiKey)) {
throw VerifyAuthenticationException::forInvalidApiKey();
}
}
public function update(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
return $response;
}
}

View File

@ -1,19 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication\Plugin;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
interface AuthenticationPluginInterface
{
/**
* @throws VerifyAuthenticationException
*/
public function verify(ServerRequestInterface $request): void;
public function update(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface;
}

View File

@ -1,55 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use function array_filter;
use function array_reduce;
use function array_shift;
class RequestToHttpAuthPlugin implements RequestToHttpAuthPluginInterface
{
// Headers here have to be defined in order of priority.
// When more than one is matched, the first one to be found will take precedence.
public const SUPPORTED_AUTH_HEADERS = [
Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
];
private AuthenticationPluginManagerInterface $authPluginManager;
public function __construct(AuthenticationPluginManagerInterface $authPluginManager)
{
$this->authPluginManager = $authPluginManager;
}
/**
* @throws MissingAuthenticationException
*/
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface
{
if (! $this->hasAnySupportedHeader($request)) {
throw MissingAuthenticationException::fromExpectedTypes(self::SUPPORTED_AUTH_HEADERS);
}
return $this->authPluginManager->get($this->getFirstAvailableHeader($request));
}
private function hasAnySupportedHeader(ServerRequestInterface $request): bool
{
return array_reduce(
self::SUPPORTED_AUTH_HEADERS,
fn (bool $carry, string $header) => $carry || $request->hasHeader($header),
false,
);
}
private function getFirstAvailableHeader(ServerRequestInterface $request): string
{
$foundHeaders = array_filter(self::SUPPORTED_AUTH_HEADERS, [$request, 'hasHeader']);
return array_shift($foundHeaders) ?? '';
}
}

View File

@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Authentication;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
interface RequestToHttpAuthPluginInterface
{
/**
* @throws MissingAuthenticationException
*/
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface;
}

View File

@ -11,19 +11,23 @@ use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPluginInterface;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use function Functional\contains;
class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterface, RequestMethodInterface
{
private array $routesWhitelist;
private RequestToHttpAuthPluginInterface $requestToAuthPlugin;
public const API_KEY_HEADER = 'X-Api-Key';
public function __construct(RequestToHttpAuthPluginInterface $requestToAuthPlugin, array $routesWhitelist)
private ApiKeyServiceInterface $apiKeyService;
private array $routesWhitelist;
public function __construct(ApiKeyServiceInterface $apiKeyService, array $routesWhitelist)
{
$this->apiKeyService = $apiKeyService;
$this->routesWhitelist = $routesWhitelist;
$this->requestToAuthPlugin = $requestToAuthPlugin;
}
public function process(Request $request, RequestHandlerInterface $handler): Response
@ -39,10 +43,20 @@ class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterfa
return $handler->handle($request);
}
$plugin = $this->requestToAuthPlugin->fromRequest($request);
$plugin->verify($request);
$response = $handler->handle($request);
$apiKey = self::apiKeyFromRequest($request);
if (empty($apiKey)) {
throw MissingAuthenticationException::fromExpectedTypes([self::API_KEY_HEADER]);
}
return $plugin->update($request, $response);
if (! $this->apiKeyService->check($apiKey)) {
throw VerifyAuthenticationException::forInvalidApiKey();
}
return $handler->handle($request);
}
public static function apiKeyFromRequest(Request $request): string
{
return $request->getHeaderLine(self::API_KEY_HEADER);
}
}

View File

@ -11,7 +11,6 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Rest\Authentication;
use function array_merge;
use function implode;
@ -27,9 +26,7 @@ class CrossDomainMiddleware implements MiddlewareInterface, RequestMethodInterfa
// Add Allow-Origin header
$response = $response->withHeader('Access-Control-Allow-Origin', $request->getHeader('Origin'))
->withHeader('Access-Control-Expose-Headers', implode(', ', [
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
]));
->withHeader('Access-Control-Expose-Headers', AuthenticationMiddleware::API_KEY_HEADER);
if ($request->getMethod() !== self::METHOD_OPTIONS) {
return $response;
}

View File

@ -4,22 +4,14 @@ declare(strict_types=1);
namespace ShlinkioApiTest\Shlink\Rest\Middleware;
use Shlinkio\Shlink\Rest\Authentication\Plugin;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
use function implode;
use function sprintf;
class AuthenticationTest extends ApiTestCase
{
/** @test */
public function authorizationErrorIsReturnedIfNoApiKeyIsSent(): void
{
$expectedDetail = sprintf(
'Expected one of the following authentication headers, ["%s"], but none were provided',
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS),
);
$expectedDetail = 'Expected one of the following authentication headers, ["X-Api-Key"], but none were provided';
$resp = $this->callApi(self::METHOD_GET, '/short-urls');
$payload = $this->getJsonResponsePayload($resp);
@ -41,7 +33,7 @@ class AuthenticationTest extends ApiTestCase
$resp = $this->callApi(self::METHOD_GET, '/short-urls', [
'headers' => [
Plugin\ApiKeyHeaderPlugin::HEADER_NAME => $apiKey,
'X-Api-Key' => $apiKey,
],
]);
$payload = $this->getJsonResponsePayload($resp);

View File

@ -1,60 +0,0 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Rest\Authentication;
use Laminas\ServiceManager\ServiceManager;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Shlinkio\Shlink\Rest\Authentication\AuthenticationPluginManager;
use Shlinkio\Shlink\Rest\Authentication\AuthenticationPluginManagerFactory;
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
class AuthenticationPluginManagerFactoryTest extends TestCase
{
use ProphecyTrait;
private AuthenticationPluginManagerFactory $factory;
public function setUp(): void
{
$this->factory = new AuthenticationPluginManagerFactory();
}
/**
* @test
* @dataProvider provideConfigs
*/
public function serviceIsProperlyCreatedWithExpectedPlugins(?array $config, array $expectedPlugins): void
{
$instance = ($this->factory)(new ServiceManager(['services' => [
'config' => $config,
]]));
self::assertEquals($expectedPlugins, $this->getPlugins($instance));
}
private function getPlugins(AuthenticationPluginManager $pluginManager): array
{
return (fn () => $this->services)->call($pluginManager);
}
public function provideConfigs(): iterable
{
yield [null, []];
yield [[], []];
yield [['auth' => []], []];
yield [['auth' => [
'plugins' => [],
]], []];
yield [['auth' => [
'plugins' => [
'services' => $plugins = [
'foo' => $this->prophesize(AuthenticationPluginInterface::class)->reveal(),
'bar' => $this->prophesize(AuthenticationPluginInterface::class)->reveal(),
],
],
]], $plugins];
}
}

View File

@ -1,69 +0,0 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Rest\Authentication\Plugin;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequest;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
class ApiKeyHeaderPluginTest extends TestCase
{
use ProphecyTrait;
private ApiKeyHeaderPlugin $plugin;
private ObjectProphecy $apiKeyService;
public function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$this->plugin = new ApiKeyHeaderPlugin($this->apiKeyService->reveal());
}
/** @test */
public function verifyThrowsExceptionWhenApiKeyIsNotValid(): void
{
$apiKey = 'abc-ABC';
$check = $this->apiKeyService->check($apiKey)->willReturn(false);
$check->shouldBeCalledOnce();
$this->expectException(VerifyAuthenticationException::class);
$this->expectExceptionMessage('Provided API key does not exist or is invalid');
$this->plugin->verify($this->createRequest($apiKey));
}
/** @test */
public function verifyDoesNotThrowExceptionWhenApiKeyIsValid(): void
{
$apiKey = 'abc-ABC';
$check = $this->apiKeyService->check($apiKey)->willReturn(true);
$this->plugin->verify($this->createRequest($apiKey));
$check->shouldHaveBeenCalledOnce();
}
/** @test */
public function updateReturnsResponseAsIs(): void
{
$apiKey = 'abc-ABC';
$response = new Response();
$returnedResponse = $this->plugin->update($this->createRequest($apiKey), $response);
self::assertSame($response, $returnedResponse);
}
private function createRequest(string $apiKey): ServerRequestInterface
{
return (new ServerRequest())->withHeader(ApiKeyHeaderPlugin::HEADER_NAME, $apiKey);
}
}

View File

@ -1,72 +0,0 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Rest\Authentication;
use Laminas\Diactoros\ServerRequest;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Rest\Authentication\AuthenticationPluginManagerInterface;
use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use function implode;
use function sprintf;
class RequestToAuthPluginTest extends TestCase
{
use ProphecyTrait;
private RequestToHttpAuthPlugin $requestToPlugin;
private ObjectProphecy $pluginManager;
public function setUp(): void
{
$this->pluginManager = $this->prophesize(AuthenticationPluginManagerInterface::class);
$this->requestToPlugin = new RequestToHttpAuthPlugin($this->pluginManager->reveal());
}
/** @test */
public function exceptionIsFoundWhenNoneOfTheSupportedMethodsIsFound(): void
{
$request = new ServerRequest();
$this->expectException(MissingAuthenticationException::class);
$this->expectExceptionMessage(sprintf(
'Expected one of the following authentication headers, ["%s"], but none were provided',
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS),
));
$this->requestToPlugin->fromRequest($request);
}
/**
* @test
* @dataProvider provideHeaders
*/
public function properPluginIsFetchedWhenAnyAuthTypeIsFound(array $headers, string $expectedHeader): void
{
$request = new ServerRequest();
foreach ($headers as $header => $value) {
$request = $request->withHeader($header, $value);
}
$plugin = $this->prophesize(AuthenticationPluginInterface::class);
$getPlugin = $this->pluginManager->get($expectedHeader)->willReturn($plugin->reveal());
$this->requestToPlugin->fromRequest($request);
$getPlugin->shouldHaveBeenCalledOnce();
}
public function provideHeaders(): iterable
{
yield 'API key header' => [[
ApiKeyHeaderPlugin::HEADER_NAME => 'foobar',
], ApiKeyHeaderPlugin::HEADER_NAME];
}
}

View File

@ -7,20 +7,21 @@ namespace ShlinkioTest\Shlink\Rest\Middleware;
use Fig\Http\Message\RequestMethodInterface;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequest;
use Laminas\Diactoros\ServerRequestFactory;
use Mezzio\Router\Route;
use Mezzio\Router\RouteResult;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Rest\Action\HealthAction;
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPluginInterface;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use function Laminas\Stratigility\middleware;
@ -29,12 +30,14 @@ class AuthenticationMiddlewareTest extends TestCase
use ProphecyTrait;
private AuthenticationMiddleware $middleware;
private ObjectProphecy $requestToPlugin;
private ObjectProphecy $apiKeyService;
private ObjectProphecy $handler;
public function setUp(): void
{
$this->requestToPlugin = $this->prophesize(RequestToHttpAuthPluginInterface::class);
$this->middleware = new AuthenticationMiddleware($this->requestToPlugin->reveal(), [HealthAction::class]);
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$this->middleware = new AuthenticationMiddleware($this->apiKeyService->reveal(), [HealthAction::class]);
$this->handler = $this->prophesize(RequestHandlerInterface::class);
}
/**
@ -43,16 +46,13 @@ class AuthenticationMiddlewareTest extends TestCase
*/
public function someWhiteListedSituationsFallbackToNextMiddleware(ServerRequestInterface $request): void
{
$handler = $this->prophesize(RequestHandlerInterface::class);
$handle = $handler->handle($request)->willReturn(new Response());
$fromRequest = $this->requestToPlugin->fromRequest(Argument::any())->willReturn(
$this->prophesize(AuthenticationPluginInterface::class)->reveal(),
);
$handle = $this->handler->handle($request)->willReturn(new Response());
$checkApiKey = $this->apiKeyService->check(Argument::any());
$this->middleware->process($request, $handler->reveal());
$this->middleware->process($request, $this->handler->reveal());
$handle->shouldHaveBeenCalledOnce();
$fromRequest->shouldNotHaveBeenCalled();
$checkApiKey->shouldNotHaveBeenCalled();
}
public function provideWhitelistedRequests(): iterable
@ -76,30 +76,70 @@ class AuthenticationMiddlewareTest extends TestCase
)->withMethod(RequestMethodInterface::METHOD_OPTIONS)];
}
/** @test */
public function updatedResponseIsReturnedWhenVerificationPasses(): void
/**
* @test
* @dataProvider provideRequestsWithoutApiKey
*/
public function throwsExceptionWhenNoApiKeyIsProvided(ServerRequestInterface $request): void
{
$newResponse = new Response();
$request = (new ServerRequest())->withAttribute(
$this->apiKeyService->check(Argument::any())->shouldNotBeCalled();
$this->handler->handle($request)->shouldNotBeCalled();
$this->expectException(MissingAuthenticationException::class);
$this->expectExceptionMessage(
'Expected one of the following authentication headers, ["X-Api-Key"], but none were provided',
);
$this->middleware->process($request, $this->handler->reveal());
}
public function provideRequestsWithoutApiKey(): iterable
{
$baseRequest = ServerRequestFactory::fromGlobals()->withAttribute(
RouteResult::class,
RouteResult::fromRoute(new Route('bar', $this->getDummyMiddleware()), []),
);
$plugin = $this->prophesize(AuthenticationPluginInterface::class);
$verify = $plugin->verify($request)->will(function (): void {
});
$update = $plugin->update($request, Argument::type(ResponseInterface::class))->willReturn($newResponse);
$fromRequest = $this->requestToPlugin->fromRequest(Argument::any())->willReturn($plugin->reveal());
yield 'no api key' => [$baseRequest];
yield 'empty api key' => [$baseRequest->withHeader('X-Api-Key', '')];
}
$handler = $this->prophesize(RequestHandlerInterface::class);
$handle = $handler->handle($request)->willReturn(new Response());
$response = $this->middleware->process($request, $handler->reveal());
/** @test */
public function throwsExceptionWhenProvidedApiKeyIsInvalid(): void
{
$apiKey = 'abc123';
$request = ServerRequestFactory::fromGlobals()
->withAttribute(
RouteResult::class,
RouteResult::fromRoute(new Route('bar', $this->getDummyMiddleware()), []),
)
->withHeader('X-Api-Key', $apiKey);
$this->apiKeyService->check($apiKey)->willReturn(false)->shouldBeCalledOnce();
$this->handler->handle($request)->shouldNotBeCalled();
$this->expectException(VerifyAuthenticationException::class);
$this->expectExceptionMessage('Provided API key does not exist or is invalid');
$this->middleware->process($request, $this->handler->reveal());
}
/** @test */
public function validApiKeyFallsBackToNextMiddleware(): void
{
$apiKey = 'abc123';
$request = ServerRequestFactory::fromGlobals()
->withAttribute(
RouteResult::class,
RouteResult::fromRoute(new Route('bar', $this->getDummyMiddleware()), []),
)
->withHeader('X-Api-Key', $apiKey);
$handle = $this->handler->handle($request)->willReturn(new Response());
$checkApiKey = $this->apiKeyService->check($apiKey)->willReturn(true);
$this->middleware->process($request, $this->handler->reveal());
self::assertSame($response, $newResponse);
$verify->shouldHaveBeenCalledOnce();
$update->shouldHaveBeenCalledOnce();
$handle->shouldHaveBeenCalledOnce();
$fromRequest->shouldHaveBeenCalledOnce();
$checkApiKey->shouldHaveBeenCalledOnce();
}
private function getDummyMiddleware(): MiddlewareInterface

View File

@ -13,7 +13,6 @@ use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Rest\Authentication;
use Shlinkio\Shlink\Rest\Middleware\CrossDomainMiddleware;
use function Laminas\Stratigility\middleware;
@ -64,10 +63,7 @@ class CrossDomainMiddlewareTest extends TestCase
$headers = $response->getHeaders();
self::assertEquals('local', $response->getHeaderLine('Access-Control-Allow-Origin'));
self::assertEquals(
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
$response->getHeaderLine('Access-Control-Expose-Headers'),
);
self::assertEquals('X-Api-Key', $response->getHeaderLine('Access-Control-Expose-Headers'));
self::assertArrayNotHasKey('Access-Control-Allow-Methods', $headers);
self::assertArrayNotHasKey('Access-Control-Max-Age', $headers);
self::assertArrayNotHasKey('Access-Control-Allow-Headers', $headers);
@ -89,10 +85,7 @@ class CrossDomainMiddlewareTest extends TestCase
$headers = $response->getHeaders();
self::assertEquals('local', $response->getHeaderLine('Access-Control-Allow-Origin'));
self::assertEquals(
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
$response->getHeaderLine('Access-Control-Expose-Headers'),
);
self::assertEquals('X-Api-Key', $response->getHeaderLine('Access-Control-Expose-Headers'));
self::assertArrayHasKey('Access-Control-Allow-Methods', $headers);
self::assertEquals('1000', $response->getHeaderLine('Access-Control-Max-Age'));
self::assertEquals('foo, bar, baz', $response->getHeaderLine('Access-Control-Allow-Headers'));