From d95cdc3296cb2c4d8721ca20a715c77c03661544 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:46:07 +0530 Subject: [PATCH 01/17] WIP: Add new console endpoint --- app/controllers/api/console.php | 33 +++++++++++++++++++ .../Modules/Sites/Http/Sites/CreateSite.php | 11 +++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 0406250024..1affc03517 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -3,9 +3,13 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; use Utopia\System\System; use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; App::init() ->groups(['console']) @@ -109,3 +113,32 @@ App::post('/v1/console/assistant') $response->chunk('', true); }); + +App::get('v1/console/resources') + ->desc('Check resource availability') + ->groups(['api', 'projects']) + ->label('scope', 'projects.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'console') + ->label('sdk.method', 'resources') + ->label('sdk.description', '/docs/references/console/resources.md') //TODO: add this file + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('type', '', new WhiteList(['rules']), 'Resource type.') + ->param('id', '', new UID(), 'ID of the resource.') + ->inject('response') + ->inject('dbForConsole') + ->action(function (string $type, string $id, Response $response, Database $dbForConsole) { + if ($type !== 'rules') { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid resource type.'); + } + + $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $id)); + + if ($document && !$document->isEmpty()) { + throw new Exception(Exception::RULE_ALREADY_EXISTS, 'Subdomain already assigned to different resource.'); + } + + $response->noContent(); + }); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php index b98dc1bb07..3647d95e65 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php @@ -18,7 +18,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -46,7 +45,7 @@ class CreateSite extends Base ->setHttpPath('/v1/sites') ->desc('Create site') ->groups(['api', 'sites']) - ->label('scope', 'sites.write') + ->label('scope', 'functions.write') ->label('event', 'sites.[siteId].create') ->label('audits.event', 'site.create') ->label('audits.resource', 'site/{response.$id}') @@ -103,15 +102,13 @@ class CreateSite extends Base $domain = ''; if (!empty($sitesDomain)) { - $ruleId = ID::unique(); $routeSubdomain = $subdomain ?: ID::unique(); $domain = "{$routeSubdomain}.{$sitesDomain}"; + $ruleId = md5($domain); - $subdomain = Authorization::skip(fn () => $dbForConsole->findOne('rules', [ - Query::equal('domain', [$domain]) - ])); + $subdomain = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $ruleId)); - if (!empty($subdomain)) { + if ($subdomain && !$subdomain->isEmpty()) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Subdomain already exists. Please choose a different subdomain.'); } } From 7836e485593ae77eec76445698b4c24ce3a37347 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:45:03 +0530 Subject: [PATCH 02/17] Use resourceId in the endpoint url --- app/config/errors.php | 7 +++++++ app/controllers/api/console.php | 14 +++++++------- src/Appwrite/Extend/Exception.php | 3 +++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index bebca87e6d..c0cb47c878 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -380,6 +380,13 @@ return [ 'code' => 409, ], + /** Console */ + Exception::RESOURCE_ALREADY_EXISTS => [ + 'name' => Exception::RESOURCE_ALREADY_EXISTS, + 'description' => 'Resource with the requested ID already exists. Please choose a different ID and try again.', + 'code' => 409, + ], + /** Membership */ Exception::MEMBERSHIP_NOT_FOUND => [ 'name' => Exception::MEMBERSHIP_NOT_FOUND, diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 1affc03517..70e8f28158 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -114,30 +114,30 @@ App::post('/v1/console/assistant') $response->chunk('', true); }); -App::get('v1/console/resources') - ->desc('Check resource availability') +App::get('v1/console/resources/:resourceId') + ->desc('Check resource ID availability') ->groups(['api', 'projects']) ->label('scope', 'projects.read') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'console') - ->label('sdk.method', 'resources') + ->label('sdk.method', 'checkResourceAvailability') ->label('sdk.description', '/docs/references/console/resources.md') //TODO: add this file ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) + ->param('resourceId', '', new UID(), 'ID of the resource.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') - ->param('id', '', new UID(), 'ID of the resource.') ->inject('response') ->inject('dbForConsole') - ->action(function (string $type, string $id, Response $response, Database $dbForConsole) { + ->action(function (string $type, string $resourceId, Response $response, Database $dbForConsole) { if ($type !== 'rules') { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid resource type.'); } - $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $id)); + $document = Authorization::skip(fn() => $dbForConsole->getDocument('rules', $resourceId)); if ($document && !$document->isEmpty()) { - throw new Exception(Exception::RULE_ALREADY_EXISTS, 'Subdomain already assigned to different resource.'); + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS, 'Resource ID is already in use.'); } $response->noContent(); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index b686cf9965..38d0245bc0 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -119,6 +119,9 @@ class Exception extends \Exception public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; public const TEAM_ALREADY_EXISTS = 'team_already_exists'; + /** Console */ + public const RESOURCE_ALREADY_EXISTS = 'resource_already_exists'; + /** Membership */ public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; From dd26a564dcd069c1616deb1e5ae56a366304f9e4 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 13 Jan 2025 00:31:45 +0530 Subject: [PATCH 03/17] Remove desc as private endpoint --- app/controllers/api/console.php | 3 +-- src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index b1885876dd..f7e6e1e7b5 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -123,7 +123,6 @@ App::get('v1/console/resources/:resourceId') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'console') ->label('sdk.method', 'checkResourceAvailability') - ->label('sdk.description', '/docs/references/console/resources.md') //TODO: add this file ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) @@ -136,7 +135,7 @@ App::get('v1/console/resources/:resourceId') throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid resource type.'); } - $document = Authorization::skip(fn() => $dbForConsole->getDocument('rules', $resourceId)); + $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $resourceId)); if ($document && !$document->isEmpty()) { throw new Exception(Exception::RESOURCE_ALREADY_EXISTS, 'Resource ID is already in use.'); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php index 4a0e219b4e..1d67a1d5c4 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php @@ -45,7 +45,7 @@ class CreateSite extends Base ->setHttpPath('/v1/sites') ->desc('Create site') ->groups(['api', 'sites']) - ->label('scope', 'functions.write') + ->label('scope', 'sites.write') ->label('event', 'sites.[siteId].create') ->label('audits.event', 'site.create') ->label('audits.resource', 'site/{response.$id}') @@ -113,7 +113,6 @@ class CreateSite extends Base if (!empty($sitesDomain)) { $routeSubdomain = $subdomain ?: ID::unique(); $domain = "{$routeSubdomain}.{$sitesDomain}"; - $ruleId = md5($domain); $subdomain = Authorization::skip(fn () => $dbForConsole->getDocument('rules', \md5($domain))); From aa130075e825f48aed13e8478e6734657cd7900e Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 13 Jan 2025 01:20:13 +0530 Subject: [PATCH 04/17] Add abuse limit --- app/controllers/api/console.php | 4 +- composer.json | 2 +- composer.lock | 288 ++++++++++++++++---------------- 3 files changed, 147 insertions(+), 147 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index f7e6e1e7b5..89a5587cb4 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -126,11 +126,13 @@ App::get('v1/console/resources/:resourceId') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) + ->label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}') ->param('resourceId', '', new UID(), 'ID of the resource.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForConsole') - ->action(function (string $type, string $resourceId, Response $response, Database $dbForConsole) { + ->action(function (string $resourceId, string $type, Response $response, Database $dbForConsole) { if ($type !== 'rules') { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid resource type.'); } diff --git a/composer.json b/composer.json index f04239dc1c..4569c84354 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "ext-openssl": "*", "ext-zlib": "*", "ext-sockets": "*", - "appwrite/php-runtimes": "0.16.*", + "appwrite/php-runtimes": "0.17.*", "appwrite/php-clamav": "2.0.*", "utopia-php/abuse": "0.43.0", "utopia-php/analytics": "0.10.*", diff --git a/composer.lock b/composer.lock index 123f6bfbe3..dcc9b7a2e1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "026d47ead39933ab29b2ea7046bfec4f", + "content-hash": "20874601c6797a65c01000471bd74645", "packages": [ { "name": "adhocore/jwt", @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.16.5", + "version": "0.17.0", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9" + "reference": "9a9e20d1f5c28caf539ad4cb52164dc283f99797" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", - "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/9a9e20d1f5c28caf539ad4cb52164dc283f99797", + "reference": "9a9e20d1f5c28caf539ad4cb52164dc283f99797", "shasum": "" }, "require": { @@ -206,9 +206,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.16.5" + "source": "https://github.com/appwrite/runtimes/tree/0.17.0" }, - "time": "2024-11-25T15:17:06+00:00" + "time": "2025-01-10T13:36:30+00:00" }, { "name": "beberlei/assert", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.29.0", + "version": "v4.29.3", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "0ef6b2eb74b782f3f9023276c324d22e440f7587" + "reference": "ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0ef6b2eb74b782f3f9023276c324d22e440f7587", - "reference": "0ef6b2eb74b782f3f9023276c324d22e440f7587", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7", + "reference": "ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.0" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.3" }, - "time": "2024-11-27T18:37:40+00:00" + "time": "2025-01-08T21:00:13+00:00" }, { "name": "jean85/pretty-package-versions", @@ -1237,16 +1237,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + "reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/351a30baa79699de3de3a814c8ccc7b52ccdfb1d", + "reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d", "shasum": "" }, "require": { @@ -1260,13 +1260,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.1.x-dev" - }, "spi": { "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] + }, + "branch-alias": { + "dev-main": "1.1.x-dev" } }, "autoload": { @@ -1303,7 +1303,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-15T22:42:37+00:00" + "time": "2025-01-08T23:50:34+00:00" }, { "name": "open-telemetry/context", @@ -1366,16 +1366,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18" + "reference": "243d9657c44a06f740cf384f486afe954c2b725f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/9b6de12204f25f8ab9540b46d6e7b5151897ce18", - "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/243d9657c44a06f740cf384f486afe954c2b725f", + "reference": "243d9657c44a06f740cf384f486afe954c2b725f", "shasum": "" }, "require": { @@ -1426,7 +1426,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-04-30T18:28:30+00:00" + "time": "2025-01-08T23:50:03+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1493,16 +1493,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.1.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b" + "reference": "9a1c3b866239dbff291e5cc555bb7793eab08127" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/fb0ff8d8279a3776bd604791e2531dd0cc147e8b", - "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/9a1c3b866239dbff291e5cc555bb7793eab08127", + "reference": "9a1c3b866239dbff291e5cc555bb7793eab08127", "shasum": "" }, "require": { @@ -1530,13 +1530,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - }, "spi": { "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] + }, + "branch-alias": { + "dev-main": "1.0.x-dev" } }, "autoload": { @@ -1579,7 +1579,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-18T21:01:35+00:00" + "time": "2025-01-08T23:50:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -2403,12 +2403,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -2453,23 +2453,23 @@ }, { "name": "symfony/http-client", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" + "reference": "339ba21476eb184290361542f732ad12c97591ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/955e43336aff03df1e8a8e17daefabb0127a313b", - "reference": "955e43336aff03df1e8a8e17daefabb0127a313b", + "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", + "reference": "339ba21476eb184290361542f732ad12c97591ec", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "~3.4.3|^3.5.1", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.0" + "source": "https://github.com/symfony/http-client/tree/v7.2.2" }, "funding": [ { @@ -2544,20 +2544,20 @@ "type": "tidelift" } ], - "time": "2024-11-29T08:22:02+00:00" + "time": "2024-12-30T18:35:15+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.1", + "version": "v3.5.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", - "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", "shasum": "" }, "require": { @@ -2565,12 +2565,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -2606,7 +2606,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" }, "funding": [ { @@ -2622,7 +2622,7 @@ "type": "tidelift" } ], - "time": "2024-11-25T12:02:18+00:00" + "time": "2024-12-07T08:49:48+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2650,8 +2650,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2724,8 +2724,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2804,8 +2804,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2884,12 +2884,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -2970,10 +2970,10 @@ }, "type": "composer-plugin", "extra": { + "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { "dev-main": "0.2.x-dev" }, - "class": "Nevay\\SPI\\Composer\\Plugin", "plugin-optional": true }, "autoload": { @@ -3929,16 +3929,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.13", + "version": "0.6.14", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "68d9b0a9477755afcda607e7e8109785cae17a13" + "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/68d9b0a9477755afcda607e7e8109785cae17a13", - "reference": "68d9b0a9477755afcda607e7e8109785cae17a13", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", + "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", "shasum": "" }, "require": { @@ -3979,9 +3979,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.13" + "source": "https://github.com/utopia-php/migration/tree/0.6.14" }, - "time": "2024-11-26T13:57:53+00:00" + "time": "2025-01-08T01:07:25+00:00" }, { "name": "utopia-php/mongo", @@ -4363,16 +4363,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.7", + "version": "0.18.8", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "0d9228faa1c202f9e01483e45a8950485f01a288" + "reference": "84737afa634e6a833fc4f8b0c967553234d3f215" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/0d9228faa1c202f9e01483e45a8950485f01a288", - "reference": "0d9228faa1c202f9e01483e45a8950485f01a288", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/84737afa634e6a833fc4f8b0c967553234d3f215", + "reference": "84737afa634e6a833fc4f8b0c967553234d3f215", "shasum": "" }, "require": { @@ -4412,9 +4412,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.7" + "source": "https://github.com/utopia-php/storage/tree/0.18.8" }, - "time": "2024-11-28T11:10:53+00:00" + "time": "2024-12-04T08:30:35+00:00" }, { "name": "utopia-php/swoole", @@ -4575,16 +4575,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.8.5", + "version": "0.8.6", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "7622330628d53844a3873ca873338150756bab82" + "reference": "b10225f54d5670f09f83e82e09de9d820ada6931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/7622330628d53844a3873ca873338150756bab82", - "reference": "7622330628d53844a3873ca873338150756bab82", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/b10225f54d5670f09f83e82e09de9d820ada6931", + "reference": "b10225f54d5670f09f83e82e09de9d820ada6931", "shasum": "" }, "require": { @@ -4618,9 +4618,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.8.5" + "source": "https://github.com/utopia-php/vcs/tree/0.8.6" }, - "time": "2024-11-11T18:33:10+00:00" + "time": "2024-12-10T13:13:23+00:00" }, { "name": "utopia-php/websocket", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.25", + "version": "0.39.29", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" + "reference": "a9c3f6076ec162588dac7b0a741bc1a2c3d1a2b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5b5323636a8d75a1c4faaae9728098dd6a6a47d1", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a9c3f6076ec162588dac7b0a741bc1a2c3d1a2b7", + "reference": "a9c3f6076ec162588dac7b0a741bc1a2c3d1a2b7", "shasum": "" }, "require": { @@ -4852,9 +4852,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.39.25" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.29" }, - "time": "2024-11-08T10:16:34+00:00" + "time": "2025-01-07T05:28:35+00:00" }, { "name": "doctrine/annotations", @@ -4934,29 +4934,27 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "1.4.10 || 2.0.3", + "phpstan/phpstan-phpunit": "^1.0 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -4964,7 +4962,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4975,9 +4973,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.4" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2024-12-07T21:18:45+00:00" }, { "name": "doctrine/instantiator", @@ -5128,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.3", + "version": "v1.19.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", - "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", + "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", "shasum": "" }, "require": { @@ -5148,10 +5146,10 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.65.0", - "illuminate/view": "^10.48.24", - "larastan/larastan": "^2.9.11", - "laravel-zero/framework": "^10.4.0", + "friendsofphp/php-cs-fixer": "^3.66.0", + "illuminate/view": "^10.48.25", + "larastan/larastan": "^2.9.12", + "laravel-zero/framework": "^10.48.25", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.17.0", "pestphp/pest": "^2.36.0" @@ -5190,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-11-26T15:34:00+00:00" + "time": "2024-12-30T16:20:10+00:00" }, { "name": "matthiasmullie/minify", @@ -5378,16 +5376,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.3.1", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -5430,9 +5428,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-10-08T18:51:32+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -5809,16 +5807,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.0", + "version": "5.6.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c" + "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c", - "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", + "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", "shasum": "" }, "require": { @@ -5867,9 +5865,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.1" }, - "time": "2024-11-12T11:25:25+00:00" + "time": "2024-12-07T09:39:29+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -7578,16 +7576,16 @@ }, { "name": "symfony/console", - "version": "v7.2.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf" + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", - "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", + "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", "shasum": "" }, "require": { @@ -7651,7 +7649,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.0" + "source": "https://github.com/symfony/console/tree/v7.2.1" }, "funding": [ { @@ -7667,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/filesystem", @@ -7737,16 +7735,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { @@ -7781,7 +7779,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.0" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -7797,7 +7795,7 @@ "type": "tidelift" } ], - "time": "2024-10-23T06:56:12+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/options-resolver", @@ -7892,8 +7890,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7968,8 +7966,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8046,8 +8044,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8124,8 +8122,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8591,5 +8589,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } From 76a01677002ed7fba6a3cc69ea9b5413be2807b5 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:15:18 +0530 Subject: [PATCH 05/17] Remove redundant check --- app/controllers/api/console.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 89a5587cb4..6af7b51995 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -133,10 +133,6 @@ App::get('v1/console/resources/:resourceId') ->inject('response') ->inject('dbForConsole') ->action(function (string $resourceId, string $type, Response $response, Database $dbForConsole) { - if ($type !== 'rules') { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid resource type.'); - } - $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $resourceId)); if ($document && !$document->isEmpty()) { From 246dc070180648bf4cb22862cf5d2f085e584267 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Thu, 23 Jan 2025 18:47:12 +0530 Subject: [PATCH 06/17] Remove unnecessary check --- app/controllers/api/console.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 6af7b51995..3052103c5b 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -135,7 +135,7 @@ App::get('v1/console/resources/:resourceId') ->action(function (string $resourceId, string $type, Response $response, Database $dbForConsole) { $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $resourceId)); - if ($document && !$document->isEmpty()) { + if (!$document->isEmpty()) { throw new Exception(Exception::RESOURCE_ALREADY_EXISTS, 'Resource ID is already in use.'); } From fcd920460fc2ecc9a15b5e26244d98da25aa7e24 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Tue, 28 Jan 2025 09:53:33 +0530 Subject: [PATCH 07/17] Addressed PR comments --- app/controllers/api/console.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 3052103c5b..4fac51c9a3 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -122,12 +122,12 @@ App::get('v1/console/resources/:resourceId') ->label('scope', 'projects.read') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'console') - ->label('sdk.method', 'checkResourceAvailability') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.method', 'getResourceAvailability') + ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.model', Response::MODEL_NONE) ->label('abuse-limit', 10) - ->label('abuse-key', 'userId:{userId}') + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) ->param('resourceId', '', new UID(), 'ID of the resource.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') @@ -136,7 +136,7 @@ App::get('v1/console/resources/:resourceId') $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $resourceId)); if (!$document->isEmpty()) { - throw new Exception(Exception::RESOURCE_ALREADY_EXISTS, 'Resource ID is already in use.'); + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); } $response->noContent(); From 7be0f4a193c3bdf121ae9c6cfd5fbcb11047a617 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:56:01 +0530 Subject: [PATCH 08/17] Add rules.read scope to console member --- app/config/roles.php | 1 + app/controllers/api/console.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/config/roles.php b/app/config/roles.php index 8bc25cfba2..a4abee0c45 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -26,6 +26,7 @@ $member = [ 'subscribers.write', 'subscribers.read', 'assistant.read', + 'rules.read' ]; $admins = [ diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 4fac51c9a3..8f593f19b9 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -119,7 +119,7 @@ App::post('/v1/console/assistant') App::get('v1/console/resources/:resourceId') ->desc('Check resource ID availability') ->groups(['api', 'projects']) - ->label('scope', 'projects.read') + ->label('scope', 'rules.read') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'console') ->label('sdk.method', 'getResourceAvailability') From 27de266cb0599af58e112651d89288b4a175944c Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:53:33 +0530 Subject: [PATCH 09/17] Add tests --- app/controllers/api/console.php | 6 +-- .../Services/Sites/SitesCustomServerTest.php | 51 +++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index d041927666..edcde23263 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -148,9 +148,9 @@ App::get('v1/console/resources/:resourceId') ->param('resourceId', '', new UID(), 'ID of the resource.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $resourceId, string $type, Response $response, Database $dbForConsole) { - $document = Authorization::skip(fn () => $dbForConsole->getDocument('rules', $resourceId)); + ->inject('dbForPlatform') + ->action(function (string $resourceId, string $type, Response $response, Database $dbForPlatform) { + $document = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $resourceId)); if (!$document->isEmpty()) { throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index d5863aea2f..841e5cb5f7 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -11,6 +11,7 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\System\System; class SitesCustomServerTest extends Scope { @@ -939,5 +940,55 @@ class SitesCustomServerTest extends Scope $this->assertArrayHasKey('adapters', $framework); } + public function testConsoleAvailabilityEndpoint(): void + { + $site = $this->createSite([ + 'buildRuntime' => 'ssr-22', + 'fallbackFile' => null, + 'framework' => 'other', + 'name' => 'Test Site', + 'subdomain' => 'test-site', + 'outputDirectory' => './', + 'siteId' => ID::unique() + ]); + + $siteId = $site['body']['$id'] ?? ''; + + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals('Test Site', $site['body']['name']); + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = "test-site.{$sitesDomain}"; + $ruleId = \md5($domain); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + ]); + + $this->assertEquals(409, $response['headers']['status-code']); // subdomain unavailable + + $domain = "non-existent-subdomain.{$sitesDomain}"; + $ruleId = \md5($domain); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // subdomain available + + $this->cleanupSite($siteId); + } + // TODO: Add tests for deletion of resources when site is deleted } From 0dc43432e2c8edbe03f15d9c4bad9e6cca86fb2d Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:06:57 +0530 Subject: [PATCH 10/17] Update SDK method structure --- app/controllers/api/console.php | 18 +++++++++++++----- .../references/console/resourceAvailability.md | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 docs/references/console/resourceAvailability.md diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index edcde23263..080059b54b 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -137,11 +137,19 @@ App::get('v1/console/resources/:resourceId') ->desc('Check resource ID availability') ->groups(['api', 'projects']) ->label('scope', 'rules.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'console') - ->label('sdk.method', 'getResourceAvailability') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'console', + name: 'resourceAvailability', + description: '/docs/references/console/resourceAvailability.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->label('abuse-limit', 10) ->label('abuse-key', 'userId:{userId}, url:{url}') ->label('abuse-time', 60) diff --git a/docs/references/console/resourceAvailability.md b/docs/references/console/resourceAvailability.md new file mode 100644 index 0000000000..8350e961b5 --- /dev/null +++ b/docs/references/console/resourceAvailability.md @@ -0,0 +1 @@ +Get availability of resources for the console. \ No newline at end of file From a322b022eb40e86b5e83138d8dd49073cf985e8b Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:25:10 +0530 Subject: [PATCH 11/17] Rename to getResourceAvailability --- app/controllers/api/console.php | 4 ++-- .../{resourceAvailability.md => getResourceAvailability.md} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/references/console/{resourceAvailability.md => getResourceAvailability.md} (100%) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 080059b54b..ab12d94f41 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -139,8 +139,8 @@ App::get('v1/console/resources/:resourceId') ->label('scope', 'rules.read') ->label('sdk', new Method( namespace: 'console', - name: 'resourceAvailability', - description: '/docs/references/console/resourceAvailability.md', + name: 'getResourceAvailability', + description: '/docs/references/console/getResourceAvailability.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/docs/references/console/resourceAvailability.md b/docs/references/console/getResourceAvailability.md similarity index 100% rename from docs/references/console/resourceAvailability.md rename to docs/references/console/getResourceAvailability.md From 681f4b9edaf14e0c8706cde5e147fee30c98492b Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Fri, 7 Feb 2025 21:29:48 +0530 Subject: [PATCH 12/17] Change to module structure --- app/controllers/api/console.php | 38 ---------- .../console/getResourceAvailability.md | 1 - src/Appwrite/Platform/Appwrite.php | 2 + .../Modules/Console/Http/Resources/Get.php | 70 +++++++++++++++++++ .../Platform/Modules/Console/Module.php | 14 ++++ .../Modules/Console/Services/Http.php | 16 +++++ .../Services/Sites/SitesCustomServerTest.php | 21 ++++-- 7 files changed, 119 insertions(+), 43 deletions(-) delete mode 100644 docs/references/console/getResourceAvailability.md create mode 100644 src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php create mode 100644 src/Appwrite/Platform/Modules/Console/Module.php create mode 100644 src/Appwrite/Platform/Modules/Console/Services/Http.php diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index ab12d94f41..d83cdc79f8 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -7,13 +7,9 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; -use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\UID; use Utopia\System\System; use Utopia\Validator\Text; -use Utopia\Validator\WhiteList; App::init() ->groups(['console']) @@ -132,37 +128,3 @@ App::post('/v1/console/assistant') $response->chunk('', true); }); - -App::get('v1/console/resources/:resourceId') - ->desc('Check resource ID availability') - ->groups(['api', 'projects']) - ->label('scope', 'rules.read') - ->label('sdk', new Method( - namespace: 'console', - name: 'getResourceAvailability', - description: '/docs/references/console/getResourceAvailability.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->label('abuse-limit', 10) - ->label('abuse-key', 'userId:{userId}, url:{url}') - ->label('abuse-time', 60) - ->param('resourceId', '', new UID(), 'ID of the resource.') - ->param('type', '', new WhiteList(['rules']), 'Resource type.') - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $resourceId, string $type, Response $response, Database $dbForPlatform) { - $document = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $resourceId)); - - if (!$document->isEmpty()) { - throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); - } - - $response->noContent(); - }); diff --git a/docs/references/console/getResourceAvailability.md b/docs/references/console/getResourceAvailability.md deleted file mode 100644 index 8350e961b5..0000000000 --- a/docs/references/console/getResourceAvailability.md +++ /dev/null @@ -1 +0,0 @@ -Get availability of resources for the console. \ No newline at end of file diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index b77ccce979..8633da6cb6 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform; +use Appwrite\Platform\Modules\Console; use Appwrite\Platform\Modules\Core; use Appwrite\Platform\Modules\Functions; use Appwrite\Platform\Modules\Sites; @@ -14,5 +15,6 @@ class Appwrite extends Platform parent::__construct(new Core()); $this->addModule(new Functions\Module()); $this->addModule(new Sites\Module()); + $this->addModule(new Console\Module()); } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php new file mode 100644 index 0000000000..7aadc10ef3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -0,0 +1,70 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('v1/console/resources/:resourceId') + ->desc('Check resource ID availability') + ->groups(['api', 'projects']) + ->label('scope', 'rules.read') + ->label('sdk', new Method( + namespace: 'console', + name: 'getResourceAvailability', + description: <<label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->param('resourceId', '', new UID(), 'ID of the resource.') + ->param('type', '', new WhiteList(['rules']), 'Resource type.') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $resourceId, string $type, Response $response, Database $dbForPlatform) + { + $document = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $resourceId)); + + if (!$document->isEmpty()) { + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + } + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Console/Module.php b/src/Appwrite/Platform/Modules/Console/Module.php new file mode 100644 index 0000000000..7bf2805479 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Module.php @@ -0,0 +1,14 @@ +addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Console/Services/Http.php b/src/Appwrite/Platform/Modules/Console/Services/Http.php new file mode 100644 index 0000000000..6221db6a96 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Services/Http.php @@ -0,0 +1,16 @@ +type = Service::TYPE_HTTP; + // Resources + $this->addAction(GetResourceAvailability::getName(), new GetResourceAvailability()); + } +} diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 841e5cb5f7..af304aa07d 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -960,9 +960,9 @@ class SitesCustomServerTest extends Scope $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = "test-site.{$sitesDomain}"; - $ruleId = \md5($domain); + $ruleId1 = \md5($domain); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId, [ + $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], @@ -974,9 +974,9 @@ class SitesCustomServerTest extends Scope $this->assertEquals(409, $response['headers']['status-code']); // subdomain unavailable $domain = "non-existent-subdomain.{$sitesDomain}"; - $ruleId = \md5($domain); + $ruleId2 = \md5($domain); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId, [ + $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId2, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], @@ -988,6 +988,19 @@ class SitesCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); // subdomain available $this->cleanupSite($siteId); + + sleep(1); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // subdomain available as site is deleted } // TODO: Add tests for deletion of resources when site is deleted From aae3b40d16626b5a15fb89e49625a210a4b774e7 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:10:44 +0530 Subject: [PATCH 13/17] Refactor console availability endpoint --- .../Modules/Console/Http/Resources/Get.php | 34 +++++++++---- .../Services/Sites/SitesCustomServerTest.php | 49 ++++++++++++++----- 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 7aadc10ef3..cc55cdb5f5 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -9,10 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Domain; +use Utopia\Validator\Text; use Utopia\Validator\WhiteList; class Get extends Action @@ -21,20 +23,20 @@ class Get extends Action public static function getName() { - return 'getResourceAvailability'; + return 'getResources'; } public function __construct() { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('v1/console/resources/:resourceId') + ->setHttpPath('v1/console/resources') ->desc('Check resource ID availability') ->groups(['api', 'projects']) ->label('scope', 'rules.read') ->label('sdk', new Method( namespace: 'console', - name: 'getResourceAvailability', + name: 'getResource', description: <<label('abuse-limit', 10) ->label('abuse-key', 'userId:{userId}, url:{url}') ->label('abuse-time', 60) - ->param('resourceId', '', new UID(), 'ID of the resource.') + ->param('value', '', new Text(256), 'Resource value.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForPlatform') ->callback([$this, 'action']); } - public function action(string $resourceId, string $type, Response $response, Database $dbForPlatform) + public function action(string $value, string $type, Response $response, Database $dbForPlatform) { - $document = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $resourceId)); + if ($type == 'rules') { + $validator = new Domain($value); - if (!$document->isEmpty()) { - throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + if (!$validator->isValid($value)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription()); + } + + $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$value]), + ])); + + if (!$document->isEmpty()) { + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + } + + $response->noContent(); } - $response->noContent(); + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid type'); } } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index d5a378616c..ab374dcdff 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -11,7 +11,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\System\System; class SitesCustomServerTest extends Scope { @@ -1294,49 +1293,73 @@ class SitesCustomServerTest extends Scope $this->assertNotEmpty($site['body']['$id']); $this->assertEquals('Test Site', $site['body']['name']); - $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - $domain = "test-site.{$sitesDomain}"; - $ruleId1 = \md5($domain); + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$siteId]) + ] + ]); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertNotEmpty($rule['body']['rules'][0]['domain']); + + $domain = $rule['body']['rules'][0]['domain']; + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $domain, ]); - $this->assertEquals(409, $response['headers']['status-code']); // subdomain unavailable + $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable - $domain = "non-existent-subdomain.{$sitesDomain}"; - $ruleId2 = \md5($domain); + $nonExistingDomain = "non-existent-subdomain.sites.localhost"; - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId2, [ + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $nonExistingDomain, ]); - $this->assertEquals(204, $response['headers']['status-code']); // subdomain available + $this->assertEquals(204, $response['headers']['status-code']); // domain available $this->cleanupSite($siteId); - sleep(1); + $this->assertEventually(function () use ($siteId) { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$siteId]) + ] + ]); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertEmpty($rule['body']['rules']); + }, 1000, 500); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $domain, ]); - $this->assertEquals(204, $response['headers']['status-code']); // subdomain available as site is deleted + $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted } // TODO: Add tests for deletion of resources when site is deleted From adb861b785a81dfbdeedb0d69664a3400f940ab1 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 12 Feb 2025 17:29:19 +0530 Subject: [PATCH 14/17] Use getSiteDomain --- .../Modules/Console/Http/Resources/Get.php | 3 +- .../Services/Sites/SitesCustomServerTest.php | 38 ++++++------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index cc55cdb5f5..e22c59f286 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -61,7 +61,7 @@ class Get extends Action public function action(string $value, string $type, Response $response, Database $dbForPlatform) { - if ($type == 'rules') { + if ($type === 'rules') { $validator = new Domain($value); if (!$validator->isValid($value)) { @@ -79,6 +79,7 @@ class Get extends Action $response->noContent(); } + // Only occurs if type is added into whitelist, but not supported in action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid type'); } } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index ab374dcdff..734bf3fc3f 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1277,35 +1277,19 @@ class SitesCustomServerTest extends Scope public function testConsoleAvailabilityEndpoint(): void { - $site = $this->createSite([ - 'buildRuntime' => 'ssr-22', - 'fallbackFile' => null, - 'framework' => 'other', + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), 'name' => 'Test Site', - 'subdomain' => 'test-site', + 'framework' => 'other', + 'buildRuntime' => 'ssr-22', 'outputDirectory' => './', - 'siteId' => ID::unique() + 'subdomain' => 'test-site', + 'fallbackFile' => null, ]); - $siteId = $site['body']['$id'] ?? ''; + $this->assertNotEmpty($siteId); - $this->assertEquals(201, $site['headers']['status-code']); - $this->assertNotEmpty($site['body']['$id']); - $this->assertEquals('Test Site', $site['body']['name']); - - $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$siteId]) - ] - ]); - - $this->assertEquals(200, $rule['headers']['status-code']); - $this->assertNotEmpty($rule['body']['rules'][0]['domain']); - - $domain = $rule['body']['rules'][0]['domain']; + $rule = $this->getSiteDomain($siteId); $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', @@ -1314,7 +1298,7 @@ class SitesCustomServerTest extends Scope 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', - 'value' => $domain, + 'value' => $rule, ]); $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable @@ -1346,7 +1330,7 @@ class SitesCustomServerTest extends Scope ]); $this->assertEquals(200, $rule['headers']['status-code']); - $this->assertEmpty($rule['body']['rules']); + $this->assertEquals(0, $rule['body']['total']); }, 1000, 500); $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ @@ -1356,7 +1340,7 @@ class SitesCustomServerTest extends Scope 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', - 'value' => $domain, + 'value' => $rule, ]); $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted From c78701ded72ed38d9532a4e0829f641b7d86c636 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 12 Feb 2025 17:54:03 +0530 Subject: [PATCH 15/17] Increase time to assert --- tests/e2e/Services/Sites/SitesCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 734bf3fc3f..33dc79dd1d 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1331,7 +1331,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(200, $rule['headers']['status-code']); $this->assertEquals(0, $rule['body']['total']); - }, 1000, 500); + }, 5000, 500); $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', From 3b0d760065aaf78a754458c710b4818b6afe8b83 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 12 Feb 2025 19:18:16 +0530 Subject: [PATCH 16/17] Increase deployment build timeout --- tests/e2e/Services/Sites/SitesBase.php | 2 +- .../Services/Sites/SitesCustomServerTest.php | 142 +++++++++--------- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/tests/e2e/Services/Sites/SitesBase.php b/tests/e2e/Services/Sites/SitesBase.php index d76e34fd24..d328d4b8fc 100644 --- a/tests/e2e/Services/Sites/SitesBase.php +++ b/tests/e2e/Services/Sites/SitesBase.php @@ -47,7 +47,7 @@ trait SitesBase 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); - }, 50000, 500); + }, 100000, 500); return $deploymentId; } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 33dc79dd1d..38f9a81452 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -65,6 +65,77 @@ class SitesCustomServerTest extends Scope $this->cleanupSite($siteId); } + public function testConsoleAvailabilityEndpoint(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Test Site', + 'framework' => 'other', + 'buildRuntime' => 'ssr-22', + 'outputDirectory' => './', + 'subdomain' => 'test-site', + 'fallbackFile' => null, + ]); + + $this->assertNotEmpty($siteId); + + $rule = $this->getSiteDomain($siteId); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $rule, + ]); + + $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable + + $nonExistingDomain = "non-existent-subdomain.sites.localhost"; + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $nonExistingDomain, + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // domain available + + $this->cleanupSite($siteId); + + $this->assertEventually(function () use ($siteId) { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$siteId]) + ] + ]); + + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertEquals(0, $rule['body']['total']); + }, 5000, 500); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $rule, + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted + } + public function testVariables(): void { $site = $this->createSite([ @@ -1275,76 +1346,5 @@ class SitesCustomServerTest extends Scope $this->cleanupSite($site['body']['$id']); } - public function testConsoleAvailabilityEndpoint(): void - { - $siteId = $this->setupSite([ - 'siteId' => ID::unique(), - 'name' => 'Test Site', - 'framework' => 'other', - 'buildRuntime' => 'ssr-22', - 'outputDirectory' => './', - 'subdomain' => 'test-site', - 'fallbackFile' => null, - ]); - - $this->assertNotEmpty($siteId); - - $rule = $this->getSiteDomain($siteId); - - $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-project' => 'console', - ], [ - 'type' => 'rules', - 'value' => $rule, - ]); - - $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable - - $nonExistingDomain = "non-existent-subdomain.sites.localhost"; - - $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-project' => 'console', - ], [ - 'type' => 'rules', - 'value' => $nonExistingDomain, - ]); - - $this->assertEquals(204, $response['headers']['status-code']); // domain available - - $this->cleanupSite($siteId); - - $this->assertEventually(function () use ($siteId) { - $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$siteId]) - ] - ]); - - $this->assertEquals(200, $rule['headers']['status-code']); - $this->assertEquals(0, $rule['body']['total']); - }, 5000, 500); - - $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'cookie' => 'a_session_console=' . $this->getRoot()['session'], - 'x-appwrite-project' => 'console', - ], [ - 'type' => 'rules', - 'value' => $rule, - ]); - - $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted - } - // TODO: Add tests for deletion of resources when site is deleted } From 0106dc78030f8e49c9bcb1aa03a60a781d0bc6df Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Wed, 12 Feb 2025 19:41:55 +0530 Subject: [PATCH 17/17] Update Get.php --- src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index e22c59f286..dc13e717f0 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -30,7 +30,7 @@ class Get extends Action { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('v1/console/resources') + ->setHttpPath('/v1/console/resources') ->desc('Check resource ID availability') ->groups(['api', 'projects']) ->label('scope', 'rules.read')