From 45d3bd6e30e112a89ffe2fcfdd3ba4bbdc384346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 23 May 2024 15:41:55 +0200 Subject: [PATCH] feat: Serialize event data and author userid to webhook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/private/EventDispatcher/WebhookCaller.php | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/lib/private/EventDispatcher/WebhookCaller.php b/lib/private/EventDispatcher/WebhookCaller.php index 2f0d1a2ab0617..0265ef317b447 100644 --- a/lib/private/EventDispatcher/WebhookCaller.php +++ b/lib/private/EventDispatcher/WebhookCaller.php @@ -28,10 +28,14 @@ use OCP\EventDispatcher\Event; use OCP\Http\Client\IClientService; +use OCP\IUserSession; +use Psr\Log\LoggerInterface; class WebhookCaller { public function __construct( private IClientService $clientService, + private IUserSession $userSession, + private LoggerInterface $logger, ) { } @@ -42,12 +46,47 @@ public function callWebhook( array $options, ): void { $client = $this->clientService->newClient(); - $client->request($method, $uri, $options + ['query' => ['event' => $event::class]]); + if (!isset($options['body'])) { + $options['body'] = json_encode([ + 'event' => $this->serializeEvent($event), + 'userid' => $this->userSession->getUser()?->getUID() ?? null, + ]); + } + try { + $response = $client->request($method, $uri, $options + ['query' => ['event' => $event::class]]); + $statusCode = $response->getStatusCode(); + if ($statusCode >= 200 && $statusCode < 300) { + $this->logger->warning('Webhook returned unexpected status code '.$statusCode, ['body' => $response->getBody()]); + } else { + $this->logger->debug('Webhook returned status code '.$statusCode, ['body' => $response->getBody()]); + } + } catch (\Exception $e) { + $this->logger->error('Webhook call failed: '.$e->getMessage(), ['exception' => $e]); + } + } - /** - * TODO: - * Serialization of the event - * Timeout or async - */ + 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 = []; + $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; + } } }