feat: require the CMS API key on /api/hotel and /api/product
This commit is contained in:
1 parent
7839b97e63
commit
32b70f9b70
3 files changed
+51
-21
No files matched your search
@@ -1,12 +1,42 @@
|
||||
# Backchannel endpoints MyE&P reads hotel and product data from. Same environment files and key
|
||||
# as content-feed.http: pick "local" and put cmsApiKey in http-client.private.env.json.
|
||||
|
||||
### GET product data for myep
|
||||
GET https://ep-reisen.ddev.site/api/product
|
||||
?product=SSTMR
|
||||
&hotel=SSTGR
|
||||
&key=abcabc123
|
||||
GET {{host}}/api/product?product=3VIIN&hotel=VLTS
|
||||
X-Api-Key: {{cmsApiKey}}
|
||||
|
||||
> {%
|
||||
client.test("200 with key", function () {
|
||||
client.assert(response.status === 200, "expected 200, got " + response.status);
|
||||
});
|
||||
%}
|
||||
|
||||
### GET hotel data for myep
|
||||
GET https://ep-reisen.ddev.site/api/hotel
|
||||
?hotel=DPWGRP
|
||||
&key=abcabc123
|
||||
GET {{host}}/api/hotel?hotel=DPWGRP
|
||||
X-Api-Key: {{cmsApiKey}}
|
||||
|
||||
> {%
|
||||
client.test("200 with key", function () {
|
||||
client.assert(response.status === 200, "expected 200, got " + response.status);
|
||||
});
|
||||
%}
|
||||
|
||||
### Transition form: key as query parameter, as MyE&P sends it today (still accepted)
|
||||
GET {{host}}/api/hotel?hotel=DPWGRP&key={{cmsApiKey}}
|
||||
|
||||
> {%
|
||||
client.test("200 with query key", function () {
|
||||
client.assert(response.status === 200, "expected 200, got " + response.status);
|
||||
});
|
||||
%}
|
||||
|
||||
### Any other value is refused now - this used to pass
|
||||
GET {{host}}/api/hotel?hotel=DPWGRP&key=AbcAbc123
|
||||
|
||||
> {%
|
||||
client.test("403 with the old dummy key", function () {
|
||||
client.assert(response.status === 403, "expected 403, got " + response.status);
|
||||
});
|
||||
%}
|
||||
|
||||
###
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace EP\EpProducts\Middleware;
|
||||
|
||||
use EP\EpProducts\ContentFeed\ContentFeedApi;
|
||||
use EP\EpProducts\Http\ApiKeyAuthenticator;
|
||||
use EP\EpProducts\Service\MyEpImageService;
|
||||
use EP\EpProducts\Utility\HotelIconUtility;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
@@ -47,13 +48,19 @@ class ApiMiddleware implements MiddlewareInterface
|
||||
*/
|
||||
private $contentFeedApi;
|
||||
|
||||
/**
|
||||
* @var ApiKeyAuthenticator
|
||||
*/
|
||||
private $authenticator;
|
||||
|
||||
public function __construct(
|
||||
MyEpImageService $hotelImageService,
|
||||
MyEpImageService $productImageService,
|
||||
MyEpImageService $regionImageService,
|
||||
FileRepository $fileRepository,
|
||||
ImageService $imageService,
|
||||
ContentFeedApi $contentFeedApi
|
||||
ContentFeedApi $contentFeedApi,
|
||||
ApiKeyAuthenticator $authenticator
|
||||
) {
|
||||
$this->hotelImageService = $hotelImageService;
|
||||
$this->productImageService = $productImageService;
|
||||
@@ -61,6 +68,7 @@ class ApiMiddleware implements MiddlewareInterface
|
||||
$this->fileRepository = $fileRepository;
|
||||
$this->imageService = $imageService;
|
||||
$this->contentFeedApi = $contentFeedApi;
|
||||
$this->authenticator = $authenticator;
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
@@ -84,12 +92,8 @@ class ApiMiddleware implements MiddlewareInterface
|
||||
|
||||
private function handleHotelRequest(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// This is currently fake, we only check for existence. Since we are communicating
|
||||
// on the backchannel only it's not much of a problem.
|
||||
$apiKey = $request->getQueryParams()['key'] ?? null;
|
||||
|
||||
if (null === $apiKey) {
|
||||
return new JsonResponse(['message' => 'No api key provided'], 403);
|
||||
if (!$this->authenticator->isAuthorized($request)) {
|
||||
return new JsonResponse(['message' => 'Invalid or missing api key'], 403);
|
||||
}
|
||||
|
||||
$hotelCode = $request->getQueryParams()['hotel'] ?? null;
|
||||
@@ -109,12 +113,8 @@ class ApiMiddleware implements MiddlewareInterface
|
||||
|
||||
private function handleProductRequest(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// This is currently fake, we only check for existence. Since we are communicating
|
||||
// on the backchannel only it's not much of a problem.
|
||||
$apiKey = $request->getQueryParams()['key'] ?? null;
|
||||
|
||||
if (null === $apiKey) {
|
||||
return new JsonResponse(['message' => 'No api key provided'], 403);
|
||||
if (!$this->authenticator->isAuthorized($request)) {
|
||||
return new JsonResponse(['message' => 'Invalid or missing api key'], 403);
|
||||
}
|
||||
|
||||
$productCode = $request->getQueryParams()['product'] ?? null;
|
||||
|
||||
@@ -76,7 +76,7 @@ productImportSftpHostKey =
|
||||
# cat=SftpImport; type=int+; label=SFTP connection timeout in seconds
|
||||
productImportSftpTimeout = 15
|
||||
|
||||
# cat=ContentFeed; type=string; label=API key for the CMS backchannel endpoints (chatbot content feed, CMS index); sent as X-Api-Key. Empty denies every request.
|
||||
# cat=ContentFeed; type=string; label=API key for the CMS backchannel endpoints used by MyE&P (/api/hotel, /api/product, /api/content/*); sent as X-Api-Key or ?key=. Empty denies every request.
|
||||
cmsApiKey =
|
||||
|
||||
# cat=ContentFeed; type=boolean; label=Serve the chatbot content feed (off: all feed endpoints answer 503)
|
||||
|
||||
Reference in new issue
Block a user