diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 24a1b28cdd..cef64ffdeb 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -4,7 +4,6 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Validator\MockNumber; use Appwrite\Event\Delete; use Appwrite\Event\Mail; -use Appwrite\Event\Validator\Event; use Appwrite\Extend\Exception; use Appwrite\Network\Platform; use Appwrite\Network\Validator\Email; @@ -30,7 +29,6 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Domains\Validator\PublicDomain; use Utopia\Http\Http; use Utopia\Locale\Locale; use Utopia\System\System; @@ -38,11 +36,9 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\Hostname; use Utopia\Validator\Integer; -use Utopia\Validator\Multiple; use Utopia\Validator\Nullable; use Utopia\Validator\Range; use Utopia\Validator\Text; -use Utopia\Validator\URL; use Utopia\Validator\WhiteList; Http::init() @@ -773,312 +769,6 @@ Http::delete('/v1/projects/:projectId') $response->noContent(); }); -// Webhooks - -Http::post('/v1/projects/:projectId/webhooks') - ->desc('Create webhook') - ->groups(['api', 'projects']) - ->label('scope', 'projects.write') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'createWebhook', - description: '/docs/references/projects/create-webhook.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_WEBHOOK, - ) - ] - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') - ->param('url', '', fn ($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) - ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') - ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) - ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN); - - $webhook = new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'projectInternalId' => $project->getSequence(), - 'projectId' => $project->getId(), - 'name' => $name, - 'events' => $events, - 'url' => $url, - 'security' => $security, - 'httpUser' => $httpUser, - 'httpPass' => $httpPass, - 'signatureKey' => \bin2hex(\random_bytes(64)), - 'enabled' => $enabled, - ]); - - $webhook = $dbForPlatform->createDocument('webhooks', $webhook); - - $dbForPlatform->purgeCachedDocument('projects', $project->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($webhook, Response::MODEL_WEBHOOK); - }); - -Http::get('/v1/projects/:projectId/webhooks') - ->desc('List webhooks') - ->groups(['api', 'projects']) - ->label('scope', 'projects.read') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'listWebhooks', - description: '/docs/references/projects/list-webhooks.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_WEBHOOK_LIST, - ) - ] - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $webhooks = $dbForPlatform->find('webhooks', [ - Query::equal('projectInternalId', [$project->getSequence()]), - Query::limit(5000), - ]); - - $response->dynamic(new Document([ - 'webhooks' => $webhooks, - 'total' => $includeTotal ? count($webhooks) : 0, - ]), Response::MODEL_WEBHOOK_LIST); - }); - -Http::get('/v1/projects/:projectId/webhooks/:webhookId') - ->desc('Get webhook') - ->groups(['api', 'projects']) - ->label('scope', 'projects.read') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'getWebhook', - description: '/docs/references/projects/get-webhook.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_WEBHOOK, - ) - ] - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform']) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $webhook = $dbForPlatform->findOne('webhooks', [ - Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), - ]); - - if ($webhook->isEmpty()) { - throw new Exception(Exception::WEBHOOK_NOT_FOUND); - } - - $response->dynamic($webhook, Response::MODEL_WEBHOOK); - }); - -Http::put('/v1/projects/:projectId/webhooks/:webhookId') - ->desc('Update webhook') - ->groups(['api', 'projects']) - ->label('scope', 'projects.write') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'updateWebhook', - description: '/docs/references/projects/update-webhook.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_WEBHOOK, - ) - ] - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform']) - ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') - ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) - ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') - ->param('url', '', fn ($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) - ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') - ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) - ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - - $webhook = $dbForPlatform->findOne('webhooks', [ - Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), - ]); - - if ($webhook->isEmpty()) { - throw new Exception(Exception::WEBHOOK_NOT_FOUND); - } - - $webhook - ->setAttribute('name', $name) - ->setAttribute('events', $events) - ->setAttribute('url', $url) - ->setAttribute('security', $security) - ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass) - ->setAttribute('enabled', $enabled); - - if ($enabled) { - $webhook->setAttribute('attempts', 0); - } - - $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForPlatform->purgeCachedDocument('projects', $project->getId()); - - $response->dynamic($webhook, Response::MODEL_WEBHOOK); - }); - -Http::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') - ->desc('Update webhook signature key') - ->groups(['api', 'projects']) - ->label('scope', 'projects.write') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'updateWebhookSignature', - description: '/docs/references/projects/update-webhook-signature.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_WEBHOOK, - ) - ] - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform']) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $webhook = $dbForPlatform->findOne('webhooks', [ - Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), - ]); - - if ($webhook->isEmpty()) { - throw new Exception(Exception::WEBHOOK_NOT_FOUND); - } - - $webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64))); - - $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForPlatform->purgeCachedDocument('projects', $project->getId()); - - $response->dynamic($webhook, Response::MODEL_WEBHOOK); - }); - -Http::delete('/v1/projects/:projectId/webhooks/:webhookId') - ->desc('Delete webhook') - ->groups(['api', 'projects']) - ->label('scope', 'projects.write') - ->label('sdk', new Method( - namespace: 'projects', - group: 'webhooks', - name: 'deleteWebhook', - description: '/docs/references/projects/delete-webhook.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform']) - ->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform']) - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if ($project->isEmpty()) { - throw new Exception(Exception::PROJECT_NOT_FOUND); - } - - $webhook = $dbForPlatform->findOne('webhooks', [ - Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), - ]); - - if ($webhook->isEmpty()) { - throw new Exception(Exception::WEBHOOK_NOT_FOUND); - } - - $dbForPlatform->deleteDocument('webhooks', $webhook->getId()); - - $dbForPlatform->purgeCachedDocument('projects', $project->getId()); - - $response->noContent(); - }); - // Keys Http::post('/v1/projects/:projectId/keys') diff --git a/app/controllers/general.php b/app/controllers/general.php index 1a099c4bde..341ac59f7a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -888,7 +888,7 @@ Http::init() $dbForProject = $getProjectDB($project); $request->addFilter(new RequestV20($dbForProject, $route->getPathValues($request))); } - if (version_compare($requestFormat, '1.9.0', '<')) { + if (version_compare($requestFormat, '1.8.2', '<')) { $request->addFilter(new RequestV21()); } } diff --git a/app/init/constants.php b/app/init/constants.php index 7a7f17f7ac..fe61316955 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -47,7 +47,7 @@ const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4321; -const APP_VERSION_STABLE = '1.8.1'; +const APP_VERSION_STABLE = '1.8.2'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/app/init/resources.php b/app/init/resources.php index 6ada4059d6..c19ceadfee 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -478,7 +478,7 @@ Http::setResource('user', function (string $mode, Document $project, Document $c return $user; }, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']); -Http::setResource('project', function ($dbForPlatform, $request, $console, $authorization) { +Http::setResource('project', function ($dbForPlatform, $request, $console, $authorization, Http $utopia) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ @@ -488,6 +488,20 @@ Http::setResource('project', function ($dbForPlatform, $request, $console, $auth $projectId = $request->getHeader('x-appwrite-project', ''); } + // Backwards compatibility for new services, originally project resources + // These endpoints moved from /v1/projects/:projectId/ to /v1/ + // When accessed via the old alias path, extract projectId from the URI + $deprecatedProjectPathPrefix = '/v1/projects/'; + $route = $utopia->match($request); + if (!empty($route)) { + $isDeprecatedAlias = \str_starts_with($request->getURI(), $deprecatedProjectPathPrefix) && + !\str_starts_with($route->getPath(), $deprecatedProjectPathPrefix); + + if ($isDeprecatedAlias) { + $projectId = \explode('/', $request->getURI(), 5)[3] ?? ''; + } + } + if (empty($projectId) || $projectId === 'console') { return $console; } @@ -495,7 +509,7 @@ Http::setResource('project', function ($dbForPlatform, $request, $console, $auth $project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForPlatform', 'request', 'console', 'authorization']); +}, ['dbForPlatform', 'request', 'console', 'authorization', 'utopia']); Http::setResource('session', function (User $user, Store $store, Token $proofForToken) { if ($user->isEmpty()) { @@ -1236,16 +1250,21 @@ function getDevice(string $root, string $connection = ''): Device } } -Http::setResource('mode', function ($request) { - /** @var Appwrite\Utopia\Request $request */ - +Http::setResource('mode', function (Request $request, Document $project) { /** * Defines the mode for the request: * - 'default' => Requests for Client and Server Side * - 'admin' => Request from the Console on non-console projects */ - return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); -}, ['request']); + $mode = $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); + + $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); + if (!empty($projectId) && $project->getId() !== $projectId) { + $mode = APP_MODE_ADMIN; + } + + return $mode; +}, ['request', 'project']); Http::setResource('geodb', function ($register) { /** @var Utopia\Registry\Registry $register */ diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 519f05de2c..8fe35608be 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -91,6 +91,7 @@ abstract class Migration '1.7.4' => 'V22', '1.8.0' => 'V23', '1.8.1' => 'V23', + '1.8.2' => 'V23', ]; /** diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php index 261571a37b..91daf33b2b 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Create.php @@ -39,6 +39,7 @@ class Create extends Base $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/webhooks') + ->httpAlias('/v1/projects/:projectId/webhooks') ->desc('Create webhook') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.write') diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php index c63a558b06..7730e9fc2c 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Delete.php @@ -32,6 +32,7 @@ class Delete extends Base $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/webhooks/:webhookId') + ->httpAlias('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Delete webhook') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.write') diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php index 229db1924d..52ac455fc9 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Get.php @@ -30,6 +30,7 @@ class Get extends Base $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/webhooks/:webhookId') + ->httpAlias('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Get webhook') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.read') 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 7995192bee..9b2612863f 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Signature/Update.php @@ -30,6 +30,7 @@ class Update extends Base { $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/webhooks/:webhookId/signature') + ->httpAlias('/v1/projects/:projectId/webhooks/:webhookId/signature') ->desc('Update webhook signature key') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.write') diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php index abc2f2ef00..a1387c356c 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/Update.php @@ -37,6 +37,7 @@ class Update extends Base { $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/webhooks/:webhookId') + ->httpAlias('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Update webhook') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.write') diff --git a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php index 35bf762ce1..fae95d7c5d 100644 --- a/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php +++ b/src/Appwrite/Platform/Modules/Webhooks/Http/Webhooks/XList.php @@ -34,6 +34,7 @@ class XList extends Base $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/webhooks') + ->httpAlias('/v1/projects/:projectId/webhooks') ->desc('List webhooks') ->groups(['api', 'webhooks']) ->label('scope', 'webhooks.read') diff --git a/src/Appwrite/Utopia/Request/Filters/V21.php b/src/Appwrite/Utopia/Request/Filters/V21.php index 4feb8e1926..d51ec28a1e 100644 --- a/src/Appwrite/Utopia/Request/Filters/V21.php +++ b/src/Appwrite/Utopia/Request/Filters/V21.php @@ -6,10 +6,13 @@ use Appwrite\Utopia\Request\Filter; class V21 extends Filter { - // Convert 1.8.0 params to 1.9.0 + // Convert 1.8.0 params to 1.8.2 public function parse(array $content, string $model): array { switch ($model) { + case 'webhooks.create': + $content = $this->fillWebhookid($content); + break; case 'functions.createTemplateDeployment': case 'sites.createTemplateDeployment': $content = $this->convertVersionToTypeAndReference($content); @@ -48,4 +51,10 @@ class V21 extends Filter return $content; } + + protected function fillWebhookid(array $content): array + { + $content['webhookId'] = $content['webhookId'] ?? 'unique()'; + return $content; + } } diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index c80ef20193..b8b6f38643 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -193,12 +193,14 @@ trait ProjectCustom $this->assertNotEmpty($devKey['body']); $this->assertNotEmpty($devKey['body']['secret']); - $webhook = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/webhooks', [ + $webhook = $this->client->call(Client::METHOD_POST, '/webhooks', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-project' => 'console', + 'x-appwrite-project' => $project['body']['$id'], + 'x-appwrite-mode' => 'admin' ], [ + 'webhookId' => 'unique()', 'name' => 'Webhook Test', 'events' => [ 'databases.*', diff --git a/tests/e2e/Services/ProjectWebhooks/WebhooksBase.php b/tests/e2e/Services/ProjectWebhooks/WebhooksBase.php index 6a251e2c52..0f1ff7eab3 100644 --- a/tests/e2e/Services/ProjectWebhooks/WebhooksBase.php +++ b/tests/e2e/Services/ProjectWebhooks/WebhooksBase.php @@ -1711,6 +1711,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', + 'X-Appwrite-Response-Format' => '1.8.0' ], [ 'name' => 'Webhook Test', 'enabled' => true, @@ -1740,6 +1741,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', + 'X-Appwrite-Response-Format' => '1.8.0' ], [ 'name' => 'Webhook Test', 'enabled' => true, @@ -1779,6 +1781,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', + 'X-Appwrite-Response-Format' => '1.8.0' ], [ 'name' => 'Webhook Test', 'enabled' => true, @@ -1824,6 +1827,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', + 'X-Appwrite-Response-Format' => '1.8.0' ])); // assert that the webhook is now disabled after 10 consecutive failures diff --git a/tests/e2e/Services/Projects/ProjectsBase.php b/tests/e2e/Services/Projects/ProjectsBase.php index dc31b7aa85..231ec302de 100644 --- a/tests/e2e/Services/Projects/ProjectsBase.php +++ b/tests/e2e/Services/Projects/ProjectsBase.php @@ -81,10 +81,12 @@ trait ProjectsBase $projectData = $this->setupProjectData(); $id = $projectData['projectId']; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ + 'webhookId' => 'unique()', 'name' => 'Webhook Test', 'events' => ['users.*.create', 'users.*.update.email'], 'url' => 'https://appwrite.io', diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 28cb146508..ce051331ce 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -2850,10 +2850,12 @@ class ProjectsConsoleClientTest extends Scope $data = $this->setupProjectData(); $id = $data['projectId']; - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ + 'webhookId' => 'unique()', 'name' => 'Webhook Test', 'events' => ['users.*.create', 'users.*.update.email'], 'url' => 'https://appwrite.io', @@ -2875,10 +2877,12 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ + 'webhookId' => 'unique()', 'name' => 'Webhook Test', 'events' => ['account.unknown', 'users.*.update.email'], 'url' => 'https://appwrite.io', @@ -2889,10 +2893,12 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ + 'webhookId' => 'unique()', 'name' => 'Webhook Test', 'events' => ['users.*.create', 'users.*.update.email'], 'url' => 'invalid://appwrite.io', @@ -2906,9 +2912,10 @@ class ProjectsConsoleClientTest extends Scope $data = $this->setupProjectWithWebhook(); $id = $data['projectId']; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2926,9 +2933,10 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; $webhookId = $data['webhookId']; - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -2944,9 +2952,10 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/webhooks/error', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']); @@ -2958,9 +2967,10 @@ class ProjectsConsoleClientTest extends Scope $id = $data['projectId']; $webhookId = $data['webhookId']; - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ 'name' => 'Webhook Test Update', 'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.create'], @@ -2982,9 +2992,10 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpPass']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); @@ -3004,9 +3015,10 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ 'name' => 'Webhook Test Update', 'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.unknown'], @@ -3016,9 +3028,10 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ 'name' => 'Webhook Test Update', 'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.create'], @@ -3028,9 +3041,10 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PUT, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ 'name' => 'Webhook Test Update', 'events' => ['users.*.delete', 'users.*.sessions.*.delete', 'buckets.*.files.*.create'], @@ -3047,9 +3061,10 @@ class ProjectsConsoleClientTest extends Scope $webhookId = $data['webhookId']; $signatureKey = $data['signatureKey']; - $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/webhooks/' . $webhookId . '/signature', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/webhooks/' . $webhookId . '/signature', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); @@ -3064,10 +3079,12 @@ class ProjectsConsoleClientTest extends Scope $id = $projectData['projectId']; // Create a webhook to delete - $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/webhooks', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), [ + 'webhookId' => 'unique()', 'name' => 'Webhook To Delete', 'events' => ['users.*.create'], 'url' => 'https://appwrite.io', @@ -3079,17 +3096,19 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $webhookId = $response['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']); @@ -3097,9 +3116,10 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/webhooks/error', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']); @@ -4457,9 +4477,10 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/webhooks/error', array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/webhooks/error', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin' ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']);