From d85e1c8f58292a0e93c395adfab04e06f4c71a26 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Sun, 3 May 2026 18:45:05 +0200 Subject: [PATCH] feat(events): make card, ACL and board events webhook-compatible Implement OCP\EventDispatcher\IWebhookCompatibleEvent on the event base classes used by Deck so the webhook_listeners app (NC >= 30) can deliver them. Card events serialize the full Card payload, ACL events serialize the Acl entity (with the token already stripped by Acl:: jsonSerialize), and BoardUpdatedEvent exposes the board id it carries. Refs nextcloud/deck#1722, nextcloud/deck#7299, nextcloud/deck#3341 Signed-off-by: Chris Coutinho --- lib/Event/AAclEvent.php | 9 ++- lib/Event/ACardEvent.php | 9 ++- lib/Event/BoardUpdatedEvent.php | 9 ++- .../Event/WebhookCompatibleEventsTest.php | 57 +++++++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/unit/Event/WebhookCompatibleEventsTest.php diff --git a/lib/Event/AAclEvent.php b/lib/Event/AAclEvent.php index fecd410f50..004d0038da 100644 --- a/lib/Event/AAclEvent.php +++ b/lib/Event/AAclEvent.php @@ -12,8 +12,9 @@ use OCA\Deck\Db\Acl; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; -abstract class AAclEvent extends Event { +abstract class AAclEvent extends Event implements IWebhookCompatibleEvent { private $acl; public function __construct(Acl $acl) { @@ -29,4 +30,10 @@ public function getAcl(): Acl { public function getBoardId(): int { return $this->acl->getBoardId(); } + + public function getWebhookSerializable(): array { + return [ + 'acl' => $this->acl->jsonSerialize(), + ]; + } } diff --git a/lib/Event/ACardEvent.php b/lib/Event/ACardEvent.php index b26620c7ad..797665b9c4 100644 --- a/lib/Event/ACardEvent.php +++ b/lib/Event/ACardEvent.php @@ -12,8 +12,9 @@ use OCA\Deck\Db\Card; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; -abstract class ACardEvent extends Event { +abstract class ACardEvent extends Event implements IWebhookCompatibleEvent { private $card; public function __construct(Card $card) { @@ -25,4 +26,10 @@ public function __construct(Card $card) { public function getCard(): Card { return $this->card; } + + public function getWebhookSerializable(): array { + return [ + 'card' => $this->card->jsonSerialize(), + ]; + } } diff --git a/lib/Event/BoardUpdatedEvent.php b/lib/Event/BoardUpdatedEvent.php index c2494c4b32..9b37c7e8dd 100644 --- a/lib/Event/BoardUpdatedEvent.php +++ b/lib/Event/BoardUpdatedEvent.php @@ -11,8 +11,9 @@ namespace OCA\Deck\Event; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; -class BoardUpdatedEvent extends Event { +class BoardUpdatedEvent extends Event implements IWebhookCompatibleEvent { private $boardId; public function __construct(int $boardId) { @@ -24,4 +25,10 @@ public function __construct(int $boardId) { public function getBoardId(): int { return $this->boardId; } + + public function getWebhookSerializable(): array { + return [ + 'boardId' => $this->boardId, + ]; + } } diff --git a/tests/unit/Event/WebhookCompatibleEventsTest.php b/tests/unit/Event/WebhookCompatibleEventsTest.php new file mode 100644 index 0000000000..ab856e5ec2 --- /dev/null +++ b/tests/unit/Event/WebhookCompatibleEventsTest.php @@ -0,0 +1,57 @@ +setId(42); + $card->setTitle('Test card'); + $card->setStackId(1); + + $event = new CardCreatedEvent($card); + + $this->assertInstanceOf(IWebhookCompatibleEvent::class, $event); + $payload = $event->getWebhookSerializable(); + $this->assertArrayHasKey('card', $payload); + $this->assertSame(42, $payload['card']['id']); + $this->assertSame('Test card', $payload['card']['title']); + } + + public function testAclEventIsWebhookCompatible(): void { + $acl = new Acl(); + $acl->setId(7); + $acl->setBoardId(3); + $acl->setType(Acl::PERMISSION_TYPE_USER); + $acl->setParticipant('alice'); + $acl->setPermissionEdit(true); + + $event = new AclCreatedEvent($acl); + + $this->assertInstanceOf(IWebhookCompatibleEvent::class, $event); + $payload = $event->getWebhookSerializable(); + $this->assertArrayHasKey('acl', $payload); + $this->assertSame(7, $payload['acl']['id']); + $this->assertSame(3, $payload['acl']['boardId']); + $this->assertArrayNotHasKey('token', $payload['acl'], 'token must be stripped from serialized ACL'); + } + + public function testBoardUpdatedEventIsWebhookCompatible(): void { + $event = new BoardUpdatedEvent(99); + + $this->assertInstanceOf(IWebhookCompatibleEvent::class, $event); + $this->assertSame(['boardId' => 99], $event->getWebhookSerializable()); + } +}