Added used API key to request

This commit is contained in:
Alejandro Celaya
2020-11-08 11:28:27 +01:00
parent 598f2d8622
commit 90551ff3bc
12 changed files with 87 additions and 44 deletions

View File

@@ -28,7 +28,7 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
]);
}
$payload[ShortUrlMetaInputFilter::API_KEY] = AuthenticationMiddleware::apiKeyFromRequest($request);
$payload[ShortUrlMetaInputFilter::API_KEY] = AuthenticationMiddleware::apiKeyFromRequest($request)->toString();
$meta = ShortUrlMeta::fromRawData($payload);
return new CreateShortUrlData($payload['longUrl'], (array) ($payload['tags'] ?? []), $meta);

View File

@@ -34,10 +34,10 @@ class SingleStepCreateShortUrlAction extends AbstractCreateShortUrlAction
protected function buildShortUrlData(Request $request): CreateShortUrlData
{
$query = $request->getQueryParams();
$apiKey = $query['apiKey'] ?? '';
$longUrl = $query['longUrl'] ?? null;
if (! $this->apiKeyService->check($apiKey)) {
$apiKeyResult = $this->apiKeyService->check($query['apiKey'] ?? '');
if (! $apiKeyResult->isValid()) {
throw ValidationException::fromArray([
'apiKey' => 'No API key was provided or it is not valid',
]);
@@ -50,7 +50,7 @@ class SingleStepCreateShortUrlAction extends AbstractCreateShortUrlAction
}
return new CreateShortUrlData($longUrl, [], ShortUrlMeta::fromRawData([
ShortUrlMetaInputFilter::API_KEY => $apiKey,
ShortUrlMetaInputFilter::API_KEY => $apiKeyResult->apiKey()->toString(),
]));
}
}

View File

@@ -54,4 +54,9 @@ class ApiKey extends AbstractEntity
{
return $this->key;
}
public function toString(): string
{
return $this->key;
}
}

View File

@@ -11,6 +11,7 @@ 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\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
@@ -43,20 +44,21 @@ class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterfa
return $handler->handle($request);
}
$apiKey = self::apiKeyFromRequest($request);
$apiKey = $request->getHeaderLine(self::API_KEY_HEADER);
if (empty($apiKey)) {
throw MissingAuthenticationException::fromExpectedTypes([self::API_KEY_HEADER]);
}
if (! $this->apiKeyService->check($apiKey)) {
$result = $this->apiKeyService->check($apiKey);
if (! $result->isValid()) {
throw VerifyAuthenticationException::forInvalidApiKey();
}
return $handler->handle($request);
return $handler->handle($request->withAttribute(ApiKey::class, $result->apiKey()));
}
public static function apiKeyFromRequest(Request $request): string
public static function apiKeyFromRequest(Request $request): ApiKey
{
return $request->getHeaderLine(self::API_KEY_HEADER);
return $request->getAttribute(ApiKey::class);
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Service;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
final class ApiKeyCheckResult
{
private ?ApiKey $apiKey;
public function __construct(?ApiKey $apiKey = null)
{
$this->apiKey = $apiKey;
}
public function isValid(): bool
{
return $this->apiKey !== null && $this->apiKey->isValid();
}
public function apiKey(): ?ApiKey
{
return $this->apiKey;
}
}

View File

@@ -29,11 +29,11 @@ class ApiKeyService implements ApiKeyServiceInterface
return $key;
}
public function check(string $key): bool
public function check(string $key): ApiKeyCheckResult
{
/** @var ApiKey|null $apiKey */
$apiKey = $this->getByKey($key);
return $apiKey !== null && $apiKey->isValid();
return new ApiKeyCheckResult($apiKey);
}
/**
@@ -63,7 +63,7 @@ class ApiKeyService implements ApiKeyServiceInterface
return $apiKeys;
}
public function getByKey(string $key): ?ApiKey
private function getByKey(string $key): ?ApiKey
{
/** @var ApiKey|null $apiKey */
$apiKey = $this->em->getRepository(ApiKey::class)->findOneBy([

View File

@@ -12,7 +12,7 @@ interface ApiKeyServiceInterface
{
public function create(?Chronos $expirationDate = null): ApiKey;
public function check(string $key): bool;
public function check(string $key): ApiKeyCheckResult;
/**
* @throws InvalidArgumentException
@@ -23,6 +23,4 @@ interface ApiKeyServiceInterface
* @return ApiKey[]
*/
public function listKeys(bool $enabledOnly = false): array;
public function getByKey(string $key): ?ApiKey;
}