mirror of
https://github.com/nextcloud/server.git
synced 2026-04-22 14:50:17 -04:00
fix: Make webhook event serialization opt-in with a new interface
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
parent
35d5d90dc0
commit
e111d2e26c
7 changed files with 45 additions and 30 deletions
|
|
@ -14,6 +14,7 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
|||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\Exception;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\EventDispatcher\IWebhookCompatibleEvent;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
|
|
@ -68,6 +69,9 @@ class WebhookListenerMapper extends QBMapper {
|
|||
AuthMethod $authMethod,
|
||||
?array $authData,
|
||||
): WebhookListener {
|
||||
if (!class_exists($event) || !is_a($event, IWebhookCompatibleEvent::class, true)) {
|
||||
throw new \UnexpectedValueException("$event is not an event class compatible with webhooks");
|
||||
}
|
||||
$webhookListener = WebhookListener::fromParams(
|
||||
[
|
||||
'appId' => $appId,
|
||||
|
|
@ -99,6 +103,9 @@ class WebhookListenerMapper extends QBMapper {
|
|||
AuthMethod $authMethod,
|
||||
?array $authData,
|
||||
): WebhookListener {
|
||||
if (!class_exists($event) || !is_a($event, IWebhookCompatibleEvent::class, true)) {
|
||||
throw new \UnexpectedValueException("$event is not an event class compatible with webhooks");
|
||||
}
|
||||
$webhookListener = WebhookListener::fromParams(
|
||||
[
|
||||
'id' => $id,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,14 @@ use OCA\Webhooks\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<Event>
|
||||
* @template-implements IEventListener<IWebhookCompatibleEvent>
|
||||
*/
|
||||
class WebhooksEventListener implements IEventListener {
|
||||
public function __construct(
|
||||
|
|
@ -55,29 +56,10 @@ class WebhooksEventListener implements IEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
private function serializeEvent(Event $event): array|\JsonSerializable {
|
||||
if ($event instanceof \JsonSerializable) {
|
||||
return $event;
|
||||
} else {
|
||||
/* Event is not serializable, we fallback to reflection to still send something */
|
||||
$data = ['class' => $event::class];
|
||||
$ref = new \ReflectionClass($event);
|
||||
foreach ($ref->getMethods() as $method) {
|
||||
if (str_starts_with($method->getName(), 'get')) {
|
||||
$key = strtolower(substr($method->getName(), 3));
|
||||
$value = $method->invoke($event);
|
||||
if ($value instanceof \OCP\Files\FileInfo) {
|
||||
$value = [
|
||||
'id' => $value->getId(),
|
||||
'path' => $value->getPath(),
|
||||
];
|
||||
}
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
$this->logger->debug('Webhook had to use fallback to serialize event '.$event::class);
|
||||
return $data;
|
||||
}
|
||||
private function serializeEvent(IWebhookCompatibleEvent $event): array {
|
||||
$data = $event->getWebhookSerializable();
|
||||
$data['class'] = $event::class;
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function filterMatch(array $filter, array $data): bool {
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ return array(
|
|||
'OCP\\EventDispatcher\\GenericEvent' => $baseDir . '/lib/public/EventDispatcher/GenericEvent.php',
|
||||
'OCP\\EventDispatcher\\IEventDispatcher' => $baseDir . '/lib/public/EventDispatcher/IEventDispatcher.php',
|
||||
'OCP\\EventDispatcher\\IEventListener' => $baseDir . '/lib/public/EventDispatcher/IEventListener.php',
|
||||
'OCP\\EventDispatcher\\IWebhookCompatibleEvent' => $baseDir . '/lib/public/EventDispatcher/IWebhookCompatibleEvent.php',
|
||||
'OCP\\EventDispatcher\\JsonSerializer' => $baseDir . '/lib/public/EventDispatcher/JsonSerializer.php',
|
||||
'OCP\\Exceptions\\AbortedEventException' => $baseDir . '/lib/public/Exceptions/AbortedEventException.php',
|
||||
'OCP\\Exceptions\\AppConfigException' => $baseDir . '/lib/public/Exceptions/AppConfigException.php',
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\EventDispatcher\\GenericEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/GenericEvent.php',
|
||||
'OCP\\EventDispatcher\\IEventDispatcher' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventDispatcher.php',
|
||||
'OCP\\EventDispatcher\\IEventListener' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventListener.php',
|
||||
'OCP\\EventDispatcher\\IWebhookCompatibleEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IWebhookCompatibleEvent.php',
|
||||
'OCP\\EventDispatcher\\JsonSerializer' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/JsonSerializer.php',
|
||||
'OCP\\Exceptions\\AbortedEventException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AbortedEventException.php',
|
||||
'OCP\\Exceptions\\AppConfigException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AppConfigException.php',
|
||||
|
|
|
|||
24
lib/public/EventDispatcher/IWebhookCompatibleEvent.php
Normal file
24
lib/public/EventDispatcher/IWebhookCompatibleEvent.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\EventDispatcher;
|
||||
|
||||
/**
|
||||
* Interface for events which can be listened to by webhooks
|
||||
*
|
||||
* @since 30.0.0
|
||||
*/
|
||||
interface IWebhookCompatibleEvent {
|
||||
/**
|
||||
* Return data to be serialized and sent to the webhook. Will be serialized using json_encode.
|
||||
*
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getWebhookSerializable(): array;
|
||||
}
|
||||
|
|
@ -9,13 +9,14 @@ declare(strict_types=1);
|
|||
namespace OCP\Files\Events\Node;
|
||||
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IWebhookCompatibleEvent;
|
||||
use OCP\EventDispatcher\JsonSerializer;
|
||||
use OCP\Files\Node;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
abstract class AbstractNodeEvent extends Event implements \JsonSerializable {
|
||||
abstract class AbstractNodeEvent extends Event implements IWebhookCompatibleEvent {
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
|
|
@ -34,9 +35,8 @@ abstract class AbstractNodeEvent extends Event implements \JsonSerializable {
|
|||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
public function getWebhookSerializable(): array {
|
||||
return [
|
||||
'class' => static::class,
|
||||
'node' => JsonSerializer::serializeFileInfo($this->node),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ declare(strict_types=1);
|
|||
namespace OCP\Files\Events\Node;
|
||||
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IWebhookCompatibleEvent;
|
||||
use OCP\EventDispatcher\JsonSerializer;
|
||||
use OCP\Files\Node;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
abstract class AbstractNodesEvent extends Event {
|
||||
abstract class AbstractNodesEvent extends Event implements IWebhookCompatibleEvent {
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
|
|
@ -42,9 +43,8 @@ abstract class AbstractNodesEvent extends Event {
|
|||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
public function getWebhookSerializable(): array {
|
||||
return [
|
||||
'class' => static::class,
|
||||
'source' => JsonSerializer::serializeFileInfo($this->source),
|
||||
'target' => JsonSerializer::serializeFileInfo($this->target),
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue