aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCôme Chilliet <come.chilliet@nextcloud.com>2024-06-06 16:12:36 +0200
committerCôme Chilliet <91878298+come-nc@users.noreply.github.com>2024-06-11 14:10:29 +0200
commite111d2e26cbc50fb252c940980574a8579ababde (patch)
tree9337e41a0befdb78cad60290c5e4f26369310b15
parent35d5d90dc01b6525fb8aabb4b71aeaa9e7b7a249 (diff)
downloadnextcloud-server-e111d2e26cbc50fb252c940980574a8579ababde.tar.gz
nextcloud-server-e111d2e26cbc50fb252c940980574a8579ababde.zip
fix: Make webhook event serialization opt-in with a new interface
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
-rw-r--r--apps/webhooks/lib/Db/WebhookListenerMapper.php7
-rw-r--r--apps/webhooks/lib/Listener/WebhooksEventListener.php30
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/public/EventDispatcher/IWebhookCompatibleEvent.php24
-rw-r--r--lib/public/Files/Events/Node/AbstractNodeEvent.php6
-rw-r--r--lib/public/Files/Events/Node/AbstractNodesEvent.php6
7 files changed, 45 insertions, 30 deletions
diff --git a/apps/webhooks/lib/Db/WebhookListenerMapper.php b/apps/webhooks/lib/Db/WebhookListenerMapper.php
index a4a43a882f5..85c167b0c92 100644
--- a/apps/webhooks/lib/Db/WebhookListenerMapper.php
+++ b/apps/webhooks/lib/Db/WebhookListenerMapper.php
@@ -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,
diff --git a/apps/webhooks/lib/Listener/WebhooksEventListener.php b/apps/webhooks/lib/Listener/WebhooksEventListener.php
index afe53595e75..37d6863553a 100644
--- a/apps/webhooks/lib/Listener/WebhooksEventListener.php
+++ b/apps/webhooks/lib/Listener/WebhooksEventListener.php
@@ -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 {
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 0fe1314644f..dbd9ebc66ab 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -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',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index cf52b9026f1..9f3b289cdfc 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.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',
diff --git a/lib/public/EventDispatcher/IWebhookCompatibleEvent.php b/lib/public/EventDispatcher/IWebhookCompatibleEvent.php
new file mode 100644
index 00000000000..b13c35c187b
--- /dev/null
+++ b/lib/public/EventDispatcher/IWebhookCompatibleEvent.php
@@ -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;
+}
diff --git a/lib/public/Files/Events/Node/AbstractNodeEvent.php b/lib/public/Files/Events/Node/AbstractNodeEvent.php
index cc27bdd8cfd..64b0e3a3aa5 100644
--- a/lib/public/Files/Events/Node/AbstractNodeEvent.php
+++ b/lib/public/Files/Events/Node/AbstractNodeEvent.php
@@ -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),
];
}
diff --git a/lib/public/Files/Events/Node/AbstractNodesEvent.php b/lib/public/Files/Events/Node/AbstractNodesEvent.php
index b5fd1b75898..7941a9e596a 100644
--- a/lib/public/Files/Events/Node/AbstractNodesEvent.php
+++ b/lib/public/Files/Events/Node/AbstractNodesEvent.php
@@ -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),
];