mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-11 17:44:44 +08:00
Added used API key to request
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,9 @@ class ApiKey extends AbstractEntity
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
27
module/Rest/src/Service/ApiKeyCheckResult.php
Normal file
27
module/Rest/src/Service/ApiKeyCheckResult.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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([
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user