mirror of
https://github.com/shlinkio/shlink.git
synced 2024-10-23 04:35:34 +03:00
Improved AuthenticationMiddleware API tests
This commit is contained in:
parent
13e795d25d
commit
509c9fe2e8
10 changed files with 57 additions and 33 deletions
|
@ -36,10 +36,7 @@ class RequestToHttpAuthPlugin implements RequestToHttpAuthPluginInterface
|
||||||
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface
|
public function fromRequest(ServerRequestInterface $request): Plugin\AuthenticationPluginInterface
|
||||||
{
|
{
|
||||||
if (! $this->hasAnySupportedHeader($request)) {
|
if (! $this->hasAnySupportedHeader($request)) {
|
||||||
throw NoAuthenticationException::fromExpectedTypes([
|
throw NoAuthenticationException::fromExpectedTypes(self::SUPPORTED_AUTH_HEADERS);
|
||||||
Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
|
|
||||||
Plugin\AuthorizationHeaderPlugin::HEADER_NAME,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->authPluginManager->get($this->getFirstAvailableHeader($request));
|
return $this->authPluginManager->get($this->getFirstAvailableHeader($request));
|
||||||
|
|
|
@ -21,12 +21,6 @@ class CreateShortUrlContentNegotiationMiddleware implements MiddlewareInterface
|
||||||
private const PLAIN_TEXT = 'text';
|
private const PLAIN_TEXT = 'text';
|
||||||
private const JSON = 'json';
|
private const JSON = 'json';
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
|
||||||
* response creation to a handler.
|
|
||||||
* @throws \RuntimeException
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
{
|
{
|
||||||
$response = $handler->handle($request);
|
$response = $handler->handle($request);
|
||||||
|
|
|
@ -6,7 +6,6 @@ namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
use function Functional\map;
|
use function Functional\map;
|
||||||
|
@ -44,7 +43,7 @@ class CreateShortUrlActionTest extends ApiTestCase
|
||||||
[$statusCode, $payload] = $this->createShortUrl(['customSlug' => $slug, 'domain' => $domain]);
|
[$statusCode, $payload] = $this->createShortUrl(['customSlug' => $slug, 'domain' => $domain]);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_BAD_REQUEST, $statusCode);
|
$this->assertEquals(self::STATUS_BAD_REQUEST, $statusCode);
|
||||||
$this->assertEquals(RestUtils::INVALID_SLUG_ERROR, $payload['error']);
|
$this->assertEquals('INVALID_SLUG', $payload['error']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class DeleteShortUrlActionTest extends ApiTestCase
|
class DeleteShortUrlActionTest extends ApiTestCase
|
||||||
|
@ -16,7 +15,7 @@ class DeleteShortUrlActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE', $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -31,6 +30,6 @@ class DeleteShortUrlActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_UNPROCESSABLE_ENTITY, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_UNPROCESSABLE_ENTITY, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_DELETION_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE_DELETION', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class EditShortUrlActionTagsTest extends ApiTestCase
|
class EditShortUrlActionTagsTest extends ApiTestCase
|
||||||
|
@ -17,7 +16,7 @@ class EditShortUrlActionTagsTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_ARGUMENT_ERROR, $error);
|
$this->assertEquals('INVALID_ARGUMENT', $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -29,6 +28,6 @@ class EditShortUrlActionTagsTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class EditShortUrlActionTest extends ApiTestCase
|
class EditShortUrlActionTest extends ApiTestCase
|
||||||
|
@ -17,7 +16,7 @@ class EditShortUrlActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE', $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -29,6 +28,6 @@ class EditShortUrlActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_ARGUMENT_ERROR, $error);
|
$this->assertEquals('INVALID_ARGUMENT', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class GetVisitsActionTest extends ApiTestCase
|
class GetVisitsActionTest extends ApiTestCase
|
||||||
|
@ -16,6 +15,6 @@ class GetVisitsActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class ResolveShortUrlActionTest extends ApiTestCase
|
class ResolveShortUrlActionTest extends ApiTestCase
|
||||||
|
@ -16,6 +15,6 @@ class ResolveShortUrlActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_SHORTCODE_ERROR, $error);
|
$this->assertEquals('INVALID_SHORTCODE', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
class UpdateTagActionTest extends ApiTestCase
|
class UpdateTagActionTest extends ApiTestCase
|
||||||
|
@ -20,7 +19,7 @@ class UpdateTagActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_ARGUMENT_ERROR, $error);
|
$this->assertEquals('INVALID_ARGUMENT', $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideInvalidBody(): iterable
|
public function provideInvalidBody(): iterable
|
||||||
|
@ -40,6 +39,6 @@ class UpdateTagActionTest extends ApiTestCase
|
||||||
['error' => $error] = $this->getJsonResponsePayload($resp);
|
['error' => $error] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::NOT_FOUND_ERROR, $error);
|
$this->assertEquals('TAG_NOT_FOUND', $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioApiTest\Shlink\Rest\Middleware;
|
namespace ShlinkioApiTest\Shlink\Rest\Middleware;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
|
use Shlinkio\Shlink\Rest\Authentication\Plugin;
|
||||||
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
|
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
|
||||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
use function implode;
|
use function implode;
|
||||||
|
@ -21,7 +20,7 @@ class AuthenticationTest extends ApiTestCase
|
||||||
['error' => $error, 'message' => $message] = $this->getJsonResponsePayload($resp);
|
['error' => $error, 'message' => $message] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_AUTHORIZATION_ERROR, $error);
|
$this->assertEquals('INVALID_AUTHORIZATION', $error);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Expected one of the following authentication headers, but none were provided, ["%s"]',
|
'Expected one of the following authentication headers, but none were provided, ["%s"]',
|
||||||
|
@ -39,13 +38,13 @@ class AuthenticationTest extends ApiTestCase
|
||||||
{
|
{
|
||||||
$resp = $this->callApi(self::METHOD_GET, '/short-codes', [
|
$resp = $this->callApi(self::METHOD_GET, '/short-codes', [
|
||||||
'headers' => [
|
'headers' => [
|
||||||
ApiKeyHeaderPlugin::HEADER_NAME => $apiKey,
|
Plugin\ApiKeyHeaderPlugin::HEADER_NAME => $apiKey,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
['error' => $error, 'message' => $message] = $this->getJsonResponsePayload($resp);
|
['error' => $error, 'message' => $message] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
|
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
|
||||||
$this->assertEquals(RestUtils::INVALID_API_KEY_ERROR, $error);
|
$this->assertEquals('INVALID_API_KEY', $error);
|
||||||
$this->assertEquals('Provided API key does not exist or is invalid.', $message);
|
$this->assertEquals('Provided API key does not exist or is invalid.', $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,4 +54,45 @@ class AuthenticationTest extends ApiTestCase
|
||||||
yield 'key which is expired' => ['expired_api_key'];
|
yield 'key which is expired' => ['expired_api_key'];
|
||||||
yield 'key which is disabled' => ['disabled_api_key'];
|
yield 'key which is disabled' => ['disabled_api_key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider provideInvalidAuthorizations
|
||||||
|
*/
|
||||||
|
public function authorizationErrorIsReturnedIfInvalidDataIsProvided(
|
||||||
|
string $authValue,
|
||||||
|
string $expectedMessage,
|
||||||
|
string $expectedError
|
||||||
|
): void {
|
||||||
|
$resp = $this->callApi(self::METHOD_GET, '/short-codes', [
|
||||||
|
'headers' => [
|
||||||
|
Plugin\AuthorizationHeaderPlugin::HEADER_NAME => $authValue,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
['error' => $error, 'message' => $message] = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
|
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
|
||||||
|
$this->assertEquals($expectedError, $error);
|
||||||
|
$this->assertEquals($expectedMessage, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideInvalidAuthorizations(): iterable
|
||||||
|
{
|
||||||
|
yield 'no type' => [
|
||||||
|
'invalid',
|
||||||
|
'You need to provide the Bearer type in the Authorization header.',
|
||||||
|
'INVALID_AUTHORIZATION',
|
||||||
|
];
|
||||||
|
yield 'invalid type' => [
|
||||||
|
'Basic invalid',
|
||||||
|
'Provided authorization type Basic is not supported. Use Bearer instead.',
|
||||||
|
'INVALID_AUTHORIZATION',
|
||||||
|
];
|
||||||
|
yield 'invalid JWT' => [
|
||||||
|
'Bearer invalid',
|
||||||
|
'Missing or invalid auth token provided. Perform a new authentication request and send provided '
|
||||||
|
. 'token on every new request on the Authorization header',
|
||||||
|
'INVALID_AUTH_TOKEN',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue