]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat: Serialize event data and author userid to webhook
authorCôme Chilliet <come.chilliet@nextcloud.com>
Thu, 23 May 2024 13:41:55 +0000 (15:41 +0200)
committerCôme Chilliet <91878298+come-nc@users.noreply.github.com>
Tue, 11 Jun 2024 12:10:29 +0000 (14:10 +0200)
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
lib/private/EventDispatcher/WebhookCaller.php

index 2f0d1a2ab06179fd3c12940baae113c6c53c8588..0265ef317b447b778359f44bf706f92ce233c877 100644 (file)
@@ -28,10 +28,14 @@ namespace OC\EventDispatcher;
 
 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 @@ class WebhookCaller {
                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;
+               }
        }
 }