feat: add the API key check and settings for the chatbot content feed
This commit is contained in:
1 parent
41d188a8cc
commit
b4a9156df6
3 files changed
+125
No files matched your search
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace EP\EpProducts\ContentFeed;
|
||||
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* The chatbot content feed's extension configuration.
|
||||
*
|
||||
* Missing keys fall back to "feed is on, but covers nothing": a key added to ext_conf_template.txt
|
||||
* is absent until the extension configuration is saved in the backend, and an empty feed is
|
||||
* refused by the consumer rather than read as "everything was deleted".
|
||||
*/
|
||||
class ContentFeedConfiguration
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
public function __construct(ExtensionConfiguration $extensionConfiguration)
|
||||
{
|
||||
$this->configuration = (array) $extensionConfiguration->get('ep_products');
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return (bool) ($this->configuration['contentFeedEnabled'] ?? true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] site identifiers
|
||||
*/
|
||||
public function getSites(): array
|
||||
{
|
||||
return GeneralUtility::trimExplode(',', (string) ($this->configuration['contentFeedSites'] ?? ''), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[] page uids whose whole subtree stays out of the feed
|
||||
*/
|
||||
public function getExcludedPages(): array
|
||||
{
|
||||
return GeneralUtility::intExplode(',', (string) ($this->configuration['contentFeedExcludedPages'] ?? ''), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int> site identifier => news detail page uid
|
||||
*/
|
||||
public function getNewsDetailPages(): array
|
||||
{
|
||||
$pages = [];
|
||||
|
||||
foreach (GeneralUtility::trimExplode(',', (string) ($this->configuration['contentFeedNewsDetailPages'] ?? ''), true) as $entry) {
|
||||
$parts = GeneralUtility::trimExplode(':', $entry, true);
|
||||
|
||||
if (2 === count($parts) && (int) $parts[1] > 0) {
|
||||
$pages[$parts[0]] = (int) $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $pages;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace EP\EpProducts\Http;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
|
||||
/**
|
||||
* Checks the shared key of the CMS backchannel endpoints (content feed, CMS index).
|
||||
*
|
||||
* An empty or missing `cmsApiKey` denies every request. ExtensionConfiguration::get() returns the
|
||||
* stored configuration verbatim, so a newly added key is absent until someone saves the extension
|
||||
* configuration in the backend - defaulting to "allow" there would publish the whole catalogue.
|
||||
*/
|
||||
class ApiKeyAuthenticator
|
||||
{
|
||||
/**
|
||||
* @var ExtensionConfiguration
|
||||
*/
|
||||
private $extensionConfiguration;
|
||||
|
||||
public function __construct(ExtensionConfiguration $extensionConfiguration)
|
||||
{
|
||||
$this->extensionConfiguration = $extensionConfiguration;
|
||||
}
|
||||
|
||||
public function isAuthorized(ServerRequestInterface $request): bool
|
||||
{
|
||||
$configured = (string) ($this->extensionConfiguration->get('ep_products')['cmsApiKey'] ?? '');
|
||||
|
||||
if ('' === $configured) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Header first: query-string keys end up in access logs. `key` stays accepted for parity
|
||||
// with the existing /api/hotel and /api/product calls.
|
||||
$provided = $request->getHeaderLine('X-Api-Key');
|
||||
|
||||
if ('' === $provided) {
|
||||
$provided = (string) ($request->getQueryParams()['key'] ?? '');
|
||||
}
|
||||
|
||||
return hash_equals($configured, $provided);
|
||||
}
|
||||
}
|
||||
@@ -75,3 +75,18 @@ 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.
|
||||
cmsApiKey =
|
||||
|
||||
# cat=ContentFeed; type=boolean; label=Serve the chatbot content feed (off: all feed endpoints answer 503)
|
||||
contentFeedEnabled = 1
|
||||
|
||||
# cat=ContentFeed; type=string; label=Site identifiers included in the chatbot content feed (comma-separated)
|
||||
contentFeedSites = ep-reisen,ser,ski-boarderweek,ski-wochenenden,snowzone
|
||||
|
||||
# cat=ContentFeed; type=string; label=Page uids whose subtrees stay out of the chatbot content feed (comma-separated; 634 = group booking links)
|
||||
contentFeedExcludedPages = 634
|
||||
|
||||
# cat=ContentFeed; type=string; label=News detail page per site for the chatbot content feed (identifier:pageUid, comma-separated)
|
||||
contentFeedNewsDetailPages = ep-reisen:1392
|
||||
Reference in new issue
Block a user