From 6b4ecbcd23b435dabb3de247dd7610ffd5dd059a Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 23 Apr 2025 18:39:55 +0400 Subject: [PATCH 1/5] fix: ensure all 4xx errors in OAuth redirect lead to the failure URL --- app/controllers/api/account.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 6a6084eb7d..1ffae4b25a 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1445,7 +1445,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!$identityWithMatchingEmail->isEmpty()) { - throw new Exception(Exception::USER_ALREADY_EXISTS); + $failureRedirect(Exception::USER_ALREADY_EXISTS); } $userWithMatchingEmail = $dbForProject->find('users', [ @@ -1453,7 +1453,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::notEqual('$id', $userId), ]); if (!empty($userWithMatchingEmail)) { - throw new Exception(Exception::USER_ALREADY_EXISTS); + $failureRedirect(Exception::USER_ALREADY_EXISTS); } $sessionUpgrade = true; @@ -1482,7 +1482,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if ($user === false || $user->isEmpty()) { // No user logged in or with OAuth2 provider ID, create new one or connect with account with same email if (empty($email)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'OAuth provider failed to return email.'); + $failureRedirect(Exception::USER_UNAUTHORIZED, 'OAuth provider failed to return email.'); } /** @@ -1525,7 +1525,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::equal('providerEmail', [$email]), ]); if (!$identityWithMatchingEmail->isEmpty()) { - throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ + $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ } try { @@ -1597,7 +1597,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!empty($identitiesWithMatchingEmail)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ + $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ } $dbForProject->createDocument('identities', new Document([ From fe28af292be088ec6aa24ab010f42167630b7279 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Wed, 23 Apr 2025 16:42:39 +0200 Subject: [PATCH 2/5] feat: allow non-critical events to ignore exceptions when enqueuing the message --- src/Appwrite/Event/Audit.php | 2 + src/Appwrite/Event/Event.php | 12 +++++- src/Appwrite/Event/Realtime.php | 11 ++++- src/Appwrite/Event/StatsResources.php | 2 + src/Appwrite/Event/StatsUsage.php | 2 + src/Appwrite/Messaging/Adapter.php | 2 +- src/Appwrite/Messaging/Adapter/Realtime.php | 45 +++++++++++---------- 7 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 6c2a9c3086..dd48093dc5 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -12,6 +12,8 @@ class Audit extends Event protected string $ip = ''; protected string $hostname = ''; + protected bool $critical = false; + public function __construct(protected Publisher $publisher) { parent::__construct($publisher); diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 08faeea485..d699a45417 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -57,6 +57,9 @@ class Event protected ?string $userId = null; protected bool $paused = false; + /** @var bool Non-critical events will not throw an exception when enqueuing of the event fails. */ + protected bool $critical = true; + /** * @param Publisher $publisher * @return void @@ -351,7 +354,14 @@ class Event // Merge the base payload with any trimmed values $payload = array_merge($this->preparePayload(), $this->trimPayload()); - return $this->publisher->enqueue($queue, $payload); + try { + return $this->publisher->enqueue($queue, $payload); + } catch (\Throwable $th) { + if ($this->critical) { + throw $th; + } + return false; + } } /** diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index 28a1bb6a6d..b77df580f8 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -2,15 +2,22 @@ namespace Appwrite\Event; +use Appwrite\Messaging\Adapter; use Appwrite\Messaging\Adapter\Realtime as RealtimeAdapter; use Utopia\Database\Document; +use Utopia\Database\Exception; class Realtime extends Event { protected array $subscribers = []; + private Adapter $realtime; + + protected bool $critical = false; + public function __construct() { + $this->realtime = new Adapter\Realtime(); } /** @@ -57,7 +64,7 @@ class Realtime extends Event * Execute Event. * * @return string|bool - * @throws InvalidArgumentException + * @throws Exception */ public function trigger(): string|bool { @@ -87,7 +94,7 @@ class Realtime extends Event : [$target['projectId'] ?? $this->getProject()->getId()]; foreach ($projectIds as $projectId) { - RealtimeAdapter::send( + $this->realtime->send( projectId: $projectId, payload: $this->getRealtimePayload(), events: $allEvents, diff --git a/src/Appwrite/Event/StatsResources.php b/src/Appwrite/Event/StatsResources.php index e7a3df97e0..c4f7ac1690 100644 --- a/src/Appwrite/Event/StatsResources.php +++ b/src/Appwrite/Event/StatsResources.php @@ -6,6 +6,8 @@ use Utopia\Queue\Publisher; class StatsResources extends Event { + protected bool $critical = false; + public function __construct(protected Publisher $publisher) { parent::__construct($publisher); diff --git a/src/Appwrite/Event/StatsUsage.php b/src/Appwrite/Event/StatsUsage.php index e259ba5e04..f6b1d695f4 100644 --- a/src/Appwrite/Event/StatsUsage.php +++ b/src/Appwrite/Event/StatsUsage.php @@ -11,6 +11,8 @@ class StatsUsage extends Event protected array $reduce = []; protected array $disabled = []; + protected bool $critical = false; + public function __construct(protected Publisher $publisher) { parent::__construct($publisher); diff --git a/src/Appwrite/Messaging/Adapter.php b/src/Appwrite/Messaging/Adapter.php index 27dd7f68eb..40169bd1a9 100644 --- a/src/Appwrite/Messaging/Adapter.php +++ b/src/Appwrite/Messaging/Adapter.php @@ -6,5 +6,5 @@ abstract class Adapter { abstract public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void; abstract public function unsubscribe(mixed $identifier): void; - abstract public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; + abstract public function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; } diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index dceafacf6e..1963bdedd6 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -7,6 +7,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Pools\Pool; class Realtime extends Adapter { @@ -35,6 +36,14 @@ class Realtime extends Adapter */ public array $subscriptions = []; + private Pool $pubsubPool; + + public function __construct() + { + global $register; + $this->pubsubPool = $register->get('pools')->get('pubsub'); + } + /** * Adds a subscription. * @@ -129,7 +138,7 @@ class Realtime extends Adapter * @param array $options * @return void */ - public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void + public function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void { if (empty($channels) || empty($roles) || empty($projectId)) { return; @@ -138,26 +147,20 @@ class Realtime extends Adapter $permissionsChanged = array_key_exists('permissionsChanged', $options) && $options['permissionsChanged']; $userId = array_key_exists('userId', $options) ? $options['userId'] : null; - global $register; - $pubsub = $register->get('pools')->get('pubsub')->pop(); - try { - /** @var \Appwrite\PubSub\Adapter $redis */ - $redis = $pubsub->getResource(); - $redis->publish('realtime', json_encode([ - 'project' => $projectId, - 'roles' => $roles, - 'permissionsChanged' => $permissionsChanged, - 'userId' => $userId, - 'data' => [ - 'events' => $events, - 'channels' => $channels, - 'timestamp' => DateTime::formatTz(DateTime::now()), - 'payload' => $payload - ] - ])); - } finally { - $pubsub->reclaim(); - } + $message = [ + 'project' => $projectId, + 'roles' => $roles, + 'permissionsChanged' => $permissionsChanged, + 'userId' => $userId, + 'data' => [ + 'events' => $events, + 'channels' => $channels, + 'timestamp' => DateTime::formatTz(DateTime::now()), + 'payload' => $payload + ] + ]; + + $this->pubsubPool->use(fn (\Appwrite\PubSub\Adapter $pubsub) => $pubsub->publish('realtime', json_encode($message))); } /** From b0eb6434b800066b013149559bb8d7205b98d35e Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Wed, 23 Apr 2025 17:12:34 +0200 Subject: [PATCH 3/5] fix: nullable group field in SDK\Method --- src/Appwrite/SDK/Method.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php index b0afd2ee58..2fec726e44 100644 --- a/src/Appwrite/SDK/Method.php +++ b/src/Appwrite/SDK/Method.php @@ -16,7 +16,7 @@ class Method * Initialise a new SDK method * * @param string $namespace - * @param string|null $group + * @param ?string $group * @param string $name * @param string $description * @param array $auth @@ -34,7 +34,7 @@ class Method */ public function __construct( protected string $namespace, - protected string|null $group, + protected ?string $group, protected string $name, protected string $description, protected array $auth, @@ -128,7 +128,7 @@ class Method return $this->namespace; } - public function getGroup(): string|null + public function getGroup(): ?string { return $this->group; } From de9b0e6eeec30958de3075ffdd7595f8b0f071f6 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 23 Apr 2025 21:18:04 +0530 Subject: [PATCH 4/5] Revert "Add configurable function and build size" --- app/controllers/api/functions.php | 11 ++-------- app/worker.php | 4 ---- src/Appwrite/Platform/Workers/Builds.php | 26 +++++++----------------- 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 2f721933fa..13db86cf4c 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1296,8 +1296,7 @@ App::post('/v1/functions/:functionId/deployments') ->inject('deviceForFunctions') ->inject('deviceForLocal') ->inject('queueForBuilds') - ->inject('plan') - ->action(function (string $functionId, ?string $entrypoint, ?string $commands, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, array $plan) { + ->action(function (string $functionId, ?string $entrypoint, ?string $commands, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -1330,14 +1329,8 @@ App::post('/v1/functions/:functionId/deployments') throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); } - $functionSizeLimit = (int) System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000'); - - if (isset($plan['functionSize'])) { - $functionSizeLimit = $plan['functionSize'] * 1000 * 1000; - } - $fileExt = new FileExt([FileExt::TYPE_GZIP]); - $fileSizeValidator = new FileSize($functionSizeLimit); + $fileSizeValidator = new FileSize(System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000')); $upload = new Upload(); // Make sure we handle a single file and multiple files the same way diff --git a/app/worker.php b/app/worker.php index f00376e074..232e0b3684 100644 --- a/app/worker.php +++ b/app/worker.php @@ -266,10 +266,6 @@ Server::setResource('timelimit', function (\Redis $redis) { Server::setResource('log', fn () => new Log()); -Server::setResource('plan', function (array $plan = []) { - return []; -}); - Server::setResource('publisher', function (Group $pools) { return $pools->get('publisher')->pop()->getResource(); }, ['pools']); diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 6392b9f3e5..4057d4b190 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -60,9 +60,8 @@ class Builds extends Action ->inject('isResourceBlocked') ->inject('log') ->inject('executor') - ->inject('plan') - ->callback(fn ($message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor, array $plan) => - $this->action($message, $project, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $usage, $cache, $dbForProject, $deviceForFunctions, $isResourceBlocked, $log, $executor, $plan)); + ->callback(fn ($message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor) => + $this->action($message, $project, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $usage, $cache, $dbForProject, $deviceForFunctions, $isResourceBlocked, $log, $executor)); } /** @@ -79,11 +78,10 @@ class Builds extends Action * @param Device $deviceForFunctions * @param Log $log * @param Executor $executor - * @param array $plan * @return void * @throws \Utopia\Database\Exception */ - public function action(Message $message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor, array $plan): void + public function action(Message $message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor): void { $payload = $message->getPayload() ?? []; @@ -104,7 +102,7 @@ class Builds extends Action case BUILD_TYPE_RETRY: Console::info('Creating build for deployment: ' . $deployment->getId()); $github = new GitHub($cache); - $this->buildDeployment($deviceForFunctions, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $dbForPlatform, $dbForProject, $github, $project, $resource, $deployment, $template, $isResourceBlocked, $log, $executor, $plan); + $this->buildDeployment($deviceForFunctions, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $dbForPlatform, $dbForProject, $github, $project, $resource, $deployment, $template, $isResourceBlocked, $log, $executor); break; default: @@ -128,12 +126,11 @@ class Builds extends Action * @param Document $template * @param Log $log * @param Executor $executor - * @param array $plan * @return void * @throws \Utopia\Database\Exception * @throws Exception */ - protected function buildDeployment(Device $deviceForFunctions, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Database $dbForPlatform, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, callable $isResourceBlocked, Log $log, Executor $executor, array $plan): void + protected function buildDeployment(Device $deviceForFunctions, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Database $dbForPlatform, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, callable $isResourceBlocked, Log $log, Executor $executor): void { $functionId = $function->getId(); $log->addTag('functionId', $function->getId()); @@ -404,15 +401,9 @@ class Builds extends Action } $directorySize = $localDevice->getDirectorySize($tmpDirectory); - $functionsSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000'); - - if (isset($plan['functionSize'])) { - $functionsSizeLimit = (int) $plan['functionSize'] * 1000 * 1000; - } - if ($directorySize > $functionsSizeLimit) { - throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / (1000 * 1000), 2) . ' MBs.'); + throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / 1048576, 2) . ' MBs.'); } Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); @@ -629,11 +620,8 @@ class Builds extends Action $durationEnd = \microtime(true); $buildSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_BUILD_SIZE_LIMIT', '2000000000'); - if (isset($plan['buildSize'])) { - $buildSizeLimit = $plan['buildSize'] * 1000 * 1000; - } if ($response['size'] > $buildSizeLimit) { - throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / (1000 * 1000), 2) . ' MBs.'); + throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.'); } /** Update the build document */ From 75efa28125393c7a54f55a668b263fcb7c4547c6 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 24 Apr 2025 11:15:23 +0000 Subject: [PATCH 5/5] core: introduce endpoint.docs in specs --- app/config/specs/open-api3-1.6.x-client.json | 3 +++ app/config/specs/open-api3-1.6.x-console.json | 3 +++ app/config/specs/open-api3-1.6.x-server.json | 3 +++ app/config/specs/open-api3-latest-client.json | 3 +++ app/config/specs/open-api3-latest-console.json | 3 +++ app/config/specs/open-api3-latest-server.json | 3 +++ app/config/specs/swagger2-1.6.x-client.json | 3 ++- app/config/specs/swagger2-1.6.x-console.json | 3 ++- app/config/specs/swagger2-1.6.x-server.json | 3 ++- app/config/specs/swagger2-latest-client.json | 3 ++- app/config/specs/swagger2-latest-console.json | 3 ++- app/config/specs/swagger2-latest-server.json | 3 ++- src/Appwrite/Platform/Tasks/Specs.php | 3 ++- src/Appwrite/Specification/Format/OpenAPI3.php | 3 +++ src/Appwrite/Specification/Format/Swagger2.php | 1 + 15 files changed, 36 insertions(+), 7 deletions(-) diff --git a/app/config/specs/open-api3-1.6.x-client.json b/app/config/specs/open-api3-1.6.x-client.json index 4a9f55f9cc..a384818bd1 100644 --- a/app/config/specs/open-api3-1.6.x-client.json +++ b/app/config/specs/open-api3-1.6.x-client.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/open-api3-1.6.x-console.json b/app/config/specs/open-api3-1.6.x-console.json index 00cddd7195..0284873ab8 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/open-api3-1.6.x-server.json b/app/config/specs/open-api3-1.6.x-server.json index 2157818d53..5b1865178e 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 4a9f55f9cc..a384818bd1 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 00cddd7195..0284873ab8 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 2157818d53..5b1865178e 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -16,6 +16,9 @@ } }, "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, { "url": "https:\/\/.cloud.appwrite.io\/v1" } diff --git a/app/config/specs/swagger2-1.6.x-client.json b/app/config/specs/swagger2-1.6.x-client.json index 6f1576f7e3..0d0303b25f 100644 --- a/app/config/specs/swagger2-1.6.x-client.json +++ b/app/config/specs/swagger2-1.6.x-client.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index 131e2826d6..bc4484a470 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index a8b2f911a4..5da541c2d0 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 6f1576f7e3..0d0303b25f 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 131e2826d6..bc4484a470 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index a8b2f911a4..5da541c2d0 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -15,7 +15,8 @@ "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, - "host": ".cloud.appwrite.io", + "host": "cloud.appwrite.io", + "x-host-docs": ".cloud.appwrite.io", "basePath": "\/v1", "schemes": [ "https" diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index cca26d3b6b..6d83f5053d 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -289,7 +289,8 @@ class Specs extends Action $formatInstance ->setParam('name', APP_NAME) ->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)') - ->setParam('endpoint', 'https://.cloud.appwrite.io/v1') + ->setParam('endpoint', 'https://cloud.appwrite.io/v1') + ->setParam('endpoint.docs', 'https://.cloud.appwrite.io/v1') ->setParam('version', APP_VERSION_STABLE) ->setParam('terms', $endpoint . '/policy/terms') ->setParam('support.email', $email) diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 3d491ab889..ccfdaad87c 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -84,6 +84,9 @@ class OpenAPI3 extends Format [ 'url' => $this->getParam('endpoint', ''), ], + [ + 'url' => $this->getParam('endpoint.docs', ''), + ], ], 'paths' => [], 'tags' => $this->services, diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 2bfe6de288..e5a8c6692e 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -80,6 +80,7 @@ class Swagger2 extends Format ], ], 'host' => \parse_url($this->getParam('endpoint', ''), PHP_URL_HOST), + 'x-host-docs' => \parse_url($this->getParam('endpoint.docs', ''), PHP_URL_HOST), 'basePath' => \parse_url($this->getParam('endpoint', ''), PHP_URL_PATH), 'schemes' => [\parse_url($this->getParam('endpoint', ''), PHP_URL_SCHEME)], 'consumes' => ['application/json', 'multipart/form-data'],