From bf375d1d40d41ebe631db94e6d99bf847df4b193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 17 Mar 2026 13:52:50 +0100 Subject: [PATCH] Fix bugs --- .../Modules/Webhooks/Http/Webhooks/Create.php | 4 +- .../Modules/Webhooks/Http/Webhooks/Delete.php | 5 +- .../Modules/Webhooks/Http/Webhooks/Get.php | 5 +- .../Http/Webhooks/Signature/Update.php | 5 +- .../Modules/Webhooks/Http/Webhooks/Update.php | 5 +- .../Modules/Webhooks/Http/Webhooks/XList.php | 3 +- .../Modules/Webhooks/Services/Http.php | 2 + tests/e2e/Services/Webhooks/WebhooksBase.php | 63 +++++++++++++------ 8 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php index d2bbd39ee8..261571a37b 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php @@ -60,7 +60,7 @@ class Create extends Base ) ], )) - ->param('webhokId', '', fn (Database $dbForPlatform) => new CustomId(false, $dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['$dbForPlatform']) + ->param('webhookId', '', fn (Database $dbForPlatform) => new CustomId(false, $dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', false, ['dbForPlatform']) ->param('url', '', fn () => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') @@ -81,8 +81,8 @@ class Create extends Base */ public function action( string $webhookId, - string $name, string $url, + string $name, array $events, bool $enabled, bool $security, diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php index 5562d080de..c63a558b06 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php @@ -54,7 +54,7 @@ class Delete extends Base ], contentType: ContentType::NONE )) - ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook ID.', false, ['$dbForPlatform']) + ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook ID.', false, ['dbForPlatform']) ->inject('project') ->inject('response') ->inject('dbForPlatform') @@ -71,7 +71,8 @@ class Delete extends Base Event $queueForEvents, Authorization $authorization ) { - $webhook = $authorization->skip(fn () => $dbForPlatform->getDocument('webhooks', $webhookId, [ + $webhook = $authorization->skip(fn () => $dbForPlatform->findOne('webhooks', [ + Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getSequence()]), ])); diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php index 3401f827aa..229db1924d 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php @@ -63,8 +63,9 @@ class Get extends Base Database $dbForPlatform, Authorization $authorization ) { - $webhook = $authorization->skip(fn () => $dbForPlatform->getDocument('webhooks', $webhookId, [ - Query::equal('projectInternalId', [$project->getSequence()]) + $webhook = $authorization->skip(fn () => $dbForPlatform->findOne('webhooks', [ + Query::equal('$id', [$webhookId]), + Query::equal('projectInternalId', [$project->getSequence()]), ])); if ($webhook->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php index 9d02404720..7995192bee 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php @@ -68,7 +68,8 @@ class Update extends Base Database $dbForPlatform, Authorization $authorization ) { - $webhook = $authorization->skip(fn () => $dbForPlatform->getDocument('webhooks', $webhookId, [ + $webhook = $authorization->skip(fn () => $dbForPlatform->findOne('webhooks', [ + Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getSequence()]), ])); @@ -80,7 +81,7 @@ class Update extends Base 'signatureKey' => \bin2hex(\random_bytes(64)), ]); - $authorization->skip(fn () => $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $updates)); + $webhook = $authorization->skip(fn () => $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $updates)); $authorization->skip(fn () => $dbForPlatform->purgeCachedDocument('projects', $project->getId())); diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php index 3f873f5174..abc2f2ef00 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php @@ -89,7 +89,8 @@ class Update extends Base Database $dbForPlatform, Authorization $authorization ) { - $webhook = $authorization->skip(fn () => $dbForPlatform->getDocument('webhooks', $webhookId, [ + $webhook = $authorization->skip(fn () => $dbForPlatform->findOne('webhooks', [ + Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getSequence()]), ])); @@ -111,7 +112,7 @@ class Update extends Base $updates->setAttribute('attempts', 0); } - $authorization->skip(fn () => $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $updates)); + $webhook = $authorization->skip(fn () => $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $updates)); $authorization->skip(fn () => $dbForPlatform->purgeCachedDocument('projects', $project->getId())); diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php index 7f753129f1..35bf762ce1 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php @@ -90,7 +90,8 @@ class XList extends Base } $webhookId = $cursor->getValue(); - $cursorDocument = $authorization->skip(fn () => $dbForPlatform->getDocument('webhooks', $webhookId, [ + $cursorDocument = $authorization->skip(fn () => $dbForPlatform->findOne('webhooks', [ + Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getSequence()]), ])); diff --git a/src/Appwrite/Platform/Modules/Webhooks/Services/Http.php b/src/Appwrite/Platform/Modules/Webhooks/Services/Http.php index d33d345bae..4805de6ebc 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Services/Http.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Webhooks\Services; use Appwrite\Platform\Modules\Webhooks\Http\Init; +use Appwrite\Platform\Modules\Webhooks\Http\Webhooks\Create as CreateWebhook; use Appwrite\Platform\Modules\Webhooks\Http\Webhooks\Delete as DeleteWebhook; use Appwrite\Platform\Modules\Webhooks\Http\Webhooks\Get as GetWebhook; use Appwrite\Platform\Modules\Webhooks\Http\Webhooks\Signature\Update as UpdateWebhookSignature; @@ -20,6 +21,7 @@ class Http extends Service $this->addAction(Init::getName(), new Init()); // Webhooks + $this->addAction(CreateWebhook::getName(), new CreateWebhook()); $this->addAction(ListWebhooks::getName(), new ListWebhooks()); $this->addAction(GetWebhook::getName(), new GetWebhook()); $this->addAction(DeleteWebhook::getName(), new DeleteWebhook()); diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index fcb3b259c6..7ad701b564 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Webhooks; use Appwrite\Tests\Async; use Tests\E2E\Client; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; @@ -1337,7 +1338,7 @@ trait WebhooksBase // Get next page using cursor $page2 = $this->listWebhooks([ Query::limit(1)->toString(), - Query::cursorAfter($cursorId)->toString(), + Query::cursorAfter(new Document(['$id' => $cursorId]))->toString(), ], true); $this->assertEquals(200, $page2['headers']['status-code']); @@ -1362,7 +1363,7 @@ trait WebhooksBase public function testListWebhooksInvalidCursor(): void { $list = $this->listWebhooks([ - Query::cursorAfter('non-existent-id')->toString(), + Query::cursorAfter(new Document(['$id' => 'non-existent-id']))->toString(), ], true); $this->assertEquals(400, $list['headers']['status-code']); @@ -1532,37 +1533,59 @@ trait WebhooksBase protected function createWebhook(string $webhookId, string $name, array $events, ?bool $enabled, ?string $url, ?bool $security, ?string $httpUser, ?string $httpPass): mixed { - $webhook = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ + $params = [ 'webhookId' => $webhookId, 'name' => $name, 'events' => $events, - 'enabled' => $enabled, 'url' => $url, - 'security' => $security, - 'httpUser' => $httpUser, - 'httpPass' => $httpPass, - ]); + ]; + + if ($enabled !== null) { + $params['enabled'] = $enabled; + } + if ($security !== null) { + $params['security'] = $security; + } + if ($httpUser !== null) { + $params['httpUser'] = $httpUser; + } + if ($httpPass !== null) { + $params['httpPass'] = $httpPass; + } + + $webhook = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); return $webhook; } protected function updateWebhook(string $webhookId, string $name, array $events, ?bool $enabled, ?string $url, ?bool $security, ?string $httpUser, ?string $httpPass): mixed { + $params = [ + 'name' => $name, + 'events' => $events, + 'url' => $url, + ]; + + if ($enabled !== null) { + $params['enabled'] = $enabled; + } + if ($security !== null) { + $params['security'] = $security; + } + if ($httpUser !== null) { + $params['httpUser'] = $httpUser; + } + if ($httpPass !== null) { + $params['httpPass'] = $httpPass; + } + $webhook = $this->client->call(Client::METHOD_PUT, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'name' => $name, - 'events' => $events, - 'enabled' => $enabled, - 'url' => $url, - 'security' => $security, - 'httpUser' => $httpUser, - 'httpPass' => $httpPass, - ]); + ], $this->getHeaders()), $params); return $webhook; }