0
0
mirror of https://github.com/nextcloud/server.git synced 2024-09-19 11:07:15 +00:00
nextcloud_server/apps/webhook_listeners/lib/Listener/WebhooksEventListener.php
Côme Chilliet 6b149be316
fix(webhook_listeners): Avoid collision between two identical calls at the same second
The job list needs argument to be unique for each registered job, so add
 a random string on top of time to make sure the same call can be
 registered several times at the same second.

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2024-08-06 12:38:26 +02:00

74 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\WebhookListeners\Listener;
use OCA\WebhookListeners\BackgroundJobs\WebhookCall;
use OCA\WebhookListeners\Db\WebhookListenerMapper;
use OCA\WebhookListeners\Service\PHPMongoQuery;
use OCP\BackgroundJob\IJobList;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\EventDispatcher\IWebhookCompatibleEvent;
use OCP\EventDispatcher\JsonSerializer;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;
/**
* The class to handle the share events
* @template-implements IEventListener<IWebhookCompatibleEvent&Event>
*/
class WebhooksEventListener implements IEventListener {
public function __construct(
private WebhookListenerMapper $mapper,
private IJobList $jobList,
private LoggerInterface $logger,
private IUserSession $userSession,
) {
}
public function handle(Event $event): void {
$user = $this->userSession->getUser();
$webhookListeners = $this->mapper->getByEvent($event::class, $user?->getUID());
foreach ($webhookListeners as $webhookListener) {
// TODO add group membership to be able to filter on it
$data = [
'event' => $this->serializeEvent($event),
'user' => (is_null($user) ? null : JsonSerializer::serializeUser($user)),
'time' => time(),
];
if ($this->filterMatch($webhookListener->getEventFilter(), $data)) {
$this->jobList->add(
WebhookCall::class,
[
$data,
$webhookListener->getId(),
/* Random string to avoid collision with another job with the same parameters */
bin2hex(random_bytes(5)),
]
);
}
}
}
private function serializeEvent(IWebhookCompatibleEvent $event): array {
$data = $event->getWebhookSerializable();
$data['class'] = $event::class;
return $data;
}
private function filterMatch(array $filter, array $data): bool {
if ($filter === []) {
return true;
}
return PHPMongoQuery::executeQuery($filter, $data);
}
}