From 54c24b24e603c96e73cfa61dba0b074ebe0ac425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 6 Nov 2024 10:52:43 +0000 Subject: [PATCH 001/340] Improve preview domains local development flow --- CONTRIBUTING.md | 12 ++++++++++++ app/controllers/general.php | 33 ++++++++++++++++++++------------- app/init.php | 11 +++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b92361e51a..e89aa369cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -613,6 +613,18 @@ If you need to clear the cache, you can do so by running the following command: docker compose exec redis redis-cli FLUSHALL ``` +## Using preview domains locally + +Appwrite Functions are automatically given a domain you can visit to execute the function. This domain has format `[SOMETHING].functions.localhost` unless you changed `_APP_DOMAIN_FUNCTIONS` environment variable. This default value works great when running Appwrite locally, but it can be impossible to use preview domains with Cloud woekspaces such as Gitpod or GitHub Codespaces. + +To use preview domains on Cloud workspaces, you can visit hostname provided by them, and supply function's preview domain as URL parameter: + +``` +https://8080-appwrite-appwrite-mjeb3ebilwv.ws-eu116.gitpod.io/ping?preview=672b3c7eab1ac523ccf5.functions.localhost +``` + +The path was set to `/ping` intentionally. Visiting `/` for preview domains might trigger Console background worker, and trigger redirect to Console without our preview URL param. Visiting different path ensures this doesnt happen. + ## Tutorials From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials: diff --git a/app/controllers/general.php b/app/controllers/general.php index b08ecb3d12..1d1e4055e4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -46,11 +46,14 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) +function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); $host = $request->getHostname() ?? ''; + if (!empty($previewHost)) { + $host = $previewHost; + } $route = Authorization::skip( fn () => $dbForConsole->find('rules', [ @@ -462,15 +465,16 @@ App::init() ->inject('queueForCertificates') ->inject('queueForFunctions') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked) { + ->inject('previewHost') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHost) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked)) { + if ($host !== $mainDomain || !empty($previewHost)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost)) { return; } } @@ -681,15 +685,16 @@ App::options() ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHost') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked)) { + if ($host !== $mainDomain || !empty($previewHost)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost)) { return; } } @@ -976,15 +981,16 @@ App::get('/robots.txt') ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHost') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if ($host === $mainDomain || $host === 'localhost') { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHost)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked); + router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost); } }); @@ -1003,15 +1009,16 @@ App::get('/humans.txt') ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHost') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if ($host === $mainDomain || $host === 'localhost') { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHost)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked); + router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost); } }); diff --git a/app/init.php b/app/init.php index d062e218e9..433d2092c5 100644 --- a/app/init.php +++ b/app/init.php @@ -1827,3 +1827,14 @@ App::setResource( 'isResourceBlocked', fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); + +App::setResource('previewHost', function (Request $request) { + if (App::isDevelopment()) { + $host = $request->getQuery('preview') ?? ''; + if (!empty($host)) { + return $host; + } + } + + return ''; +}, ['request']); From ca887f018e5343fe8f50d21e98776ce6da17ae54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 6 Nov 2024 11:29:24 +0000 Subject: [PATCH 002/340] fix domain execution response size --- app/controllers/general.php | 42 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1d1e4055e4..467c8b0aca 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -355,26 +355,6 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo throw $th; } } finally { - $fileSize = 0; - $file = $request->getFiles('file'); - if (!empty($file)) { - $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; - } - - $queueForUsage - ->addMetric(METRIC_NETWORK_REQUESTS, 1) - ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) - ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) - ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function - ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->setProject($project) - ->trigger() - ; - $queueForFunctions ->setType(Func::TYPE_ASYNC_WRITE) ->setExecution($execution) @@ -409,6 +389,28 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo ->setStatusCode($execution['responseStatusCode'] ?? 200) ->send($body); + $fileSize = 0; + $file = $request->getFiles('file'); + if (!empty($file)) { + $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; + } + + \var_dump($response->getSize()); + + $queueForUsage + ->addMetric(METRIC_NETWORK_REQUESTS, 1) + ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) + ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) + ->addMetric(METRIC_EXECUTIONS, 1) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->setProject($project) + ->trigger() + ; + return true; } elseif ($type === 'api') { $utopia->getRoute()?->label('error', ''); From 87cfd7df3ba527cb26ad624c353bb00e8e6c9f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 6 Nov 2024 11:39:44 +0000 Subject: [PATCH 003/340] Remove leftover --- app/controllers/general.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 467c8b0aca..e453fa3200 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -395,8 +395,6 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } - \var_dump($response->getSize()); - $queueForUsage ->addMetric(METRIC_NETWORK_REQUESTS, 1) ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) From c9e6ef820211c73506d1129e3887b7f8732384b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 6 Nov 2024 16:05:58 +0000 Subject: [PATCH 004/340] Rename based on PR reviews --- app/controllers/general.php | 38 ++++++++++++++++++------------------- app/init.php | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1d1e4055e4..a8ca5985f8 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -46,13 +46,13 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) +function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); $host = $request->getHostname() ?? ''; - if (!empty($previewHost)) { - $host = $previewHost; + if (!empty($previewHostname)) { + $host = $previewHostname; } $route = Authorization::skip( @@ -465,16 +465,16 @@ App::init() ->inject('queueForCertificates') ->inject('queueForFunctions') ->inject('isResourceBlocked') - ->inject('previewHost') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHost) { + ->inject('previewHostname') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain || !empty($previewHost)) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost)) { + if ($host !== $mainDomain || !empty($previewHostname)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { return; } } @@ -685,16 +685,16 @@ App::options() ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->inject('previewHost') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { + ->inject('previewHostname') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain || !empty($previewHost)) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost)) { + if ($host !== $mainDomain || !empty($previewHostname)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { return; } } @@ -981,16 +981,16 @@ App::get('/robots.txt') ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->inject('previewHost') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { + ->inject('previewHostname') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if (($host === $mainDomain || $host === 'localhost') && empty($previewHost)) { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost); + router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); } }); @@ -1009,16 +1009,16 @@ App::get('/humans.txt') ->inject('queueForFunctions') ->inject('geodb') ->inject('isResourceBlocked') - ->inject('previewHost') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHost) { + ->inject('previewHostname') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if (($host === $mainDomain || $host === 'localhost') && empty($previewHost)) { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHost); + router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); } }); diff --git a/app/init.php b/app/init.php index 433d2092c5..c7a87c8dc9 100644 --- a/app/init.php +++ b/app/init.php @@ -1828,9 +1828,9 @@ App::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); -App::setResource('previewHost', function (Request $request) { +App::setResource('previewHostname', function (Request $request) { if (App::isDevelopment()) { - $host = $request->getQuery('preview') ?? ''; + $host = $request->getQuery('appwrite-hostname') ?? ''; if (!empty($host)) { return $host; } From 4ee9e9730fe515a0d10b5c4c25d40570641e9933 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 7 Nov 2024 12:05:37 +0100 Subject: [PATCH 005/340] feat: realtime ping pong --- .gitignore | 1 + app/realtime.php | 12 ++++++--- .../Realtime/RealtimeCustomClientTest.php | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5ae03e2a56..0d2b4b51ff 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ dev/yasd_init.php .phpunit.result.cache Makefile appwrite.json +.zed/ \ No newline at end of file diff --git a/app/realtime.php b/app/realtime.php index b8fdb2cf21..160b33d8d5 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -582,9 +582,15 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re } switch ($message['type']) { - /** - * This type is used to authenticate. - */ + case 'ping': + $server->send([$connection], json_encode([ + 'type' => 'pong' + ])); + + break; + /** + * This type is used to authenticate. + */ case 'authentication': if (!array_key_exists('session', $message['data'])) { throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Payload is not valid.'); diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index c3372b98c5..2b3d874e7c 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -7,6 +7,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; +use Tests\E2E\Services\Functions\FunctionsBase; use Utopia\CLI\Console; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -15,6 +16,7 @@ use WebSocket\ConnectionException; class RealtimeCustomClientTest extends Scope { + use FunctionsBase; use RealtimeBase; use ProjectCustom; use SideClient; @@ -110,6 +112,30 @@ class RealtimeCustomClientTest extends Scope $client->close(); } + public function testPingPong() + { + $client = $this->getWebsocket(['files'], [ + 'origin' => 'http://localhost' + ]); + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('files', $response['data']['channels']); + + $client->send(\json_encode([ + 'type' => 'ping' + ])); + + $response = json_decode($client->receive(), true); + $this->assertEquals('pong', $response['type']); + + $client->close(); + } + public function testManualAuthentication() { $user = $this->getUser(); From f91f382baf010962d2399087d26a5a70d6c63673 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 7 Nov 2024 12:08:11 +0100 Subject: [PATCH 006/340] style: remove unnecessary comment --- app/realtime.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index 160b33d8d5..d8137a7a5a 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -588,9 +588,6 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re ])); break; - /** - * This type is used to authenticate. - */ case 'authentication': if (!array_key_exists('session', $message['data'])) { throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Payload is not valid.'); From a6779caa5ebf0eca8a080061fca91931a1e9842b Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 7 Nov 2024 14:28:39 +0200 Subject: [PATCH 007/340] Trigger sentry --- src/Appwrite/Platform/Workers/Databases.php | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index f697e7be13..1974a0b959 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -92,6 +92,7 @@ class Databases extends Action * @throws Authorization * @throws Conflict * @throws \Exception + * @throws \Throwable */ private function createAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void { @@ -134,7 +135,6 @@ class Databases extends Action $options = $attribute->getAttribute('options', []); $project = $dbForConsole->getDocument('projects', $projectId); - try { switch ($type) { case Database::VAR_RELATIONSHIP: @@ -170,7 +170,6 @@ class Databases extends Action $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); } catch (\Throwable $e) { - // TODO: Send non DatabaseExceptions to Sentry Console::error($e->getMessage()); if ($e instanceof DatabaseException) { @@ -193,6 +192,9 @@ class Databases extends Action $relatedAttribute->setAttribute('status', 'failed') ); } + + // TODO: Send non DatabaseExceptions to Sentry + throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); } @@ -215,6 +217,7 @@ class Databases extends Action * @throws Authorization * @throws Conflict * @throws \Exception + * @throws \Throwable **/ private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void { @@ -273,7 +276,6 @@ class Databases extends Action $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } } catch (\Throwable $e) { - // TODO: Send non DatabaseExceptions to Sentry Console::error($e->getMessage()); if ($e instanceof DatabaseException) { @@ -294,6 +296,9 @@ class Databases extends Action $relatedAttribute->setAttribute('status', 'stuck') ); } + + // TODO: Send non DatabaseExceptions to Sentry + throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); } @@ -370,6 +375,7 @@ class Databases extends Action * @throws Conflict * @throws Structure * @throws DatabaseException + * @throws \Throwable */ private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void { @@ -401,7 +407,7 @@ class Databases extends Action } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); } catch (\Throwable $e) { - // TODO: Send non DatabaseExceptions to Sentry + Console::error($e->getMessage()); if ($e instanceof DatabaseException) { @@ -412,6 +418,9 @@ class Databases extends Action $index->getId(), $index->setAttribute('status', 'failed') ); + + // TODO: Send non DatabaseExceptions to Sentry + throw $e; } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); } @@ -431,6 +440,7 @@ class Databases extends Action * @throws Conflict * @throws Structure * @throws DatabaseException + * @throws \Throwable */ private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void { @@ -459,7 +469,6 @@ class Databases extends Action $dbForProject->deleteDocument('indexes', $index->getId()); $index->setAttribute('status', 'deleted'); } catch (\Throwable $e) { - // TODO: Send non DatabaseExceptions to Sentry Console::error($e->getMessage()); if ($e instanceof DatabaseException) { @@ -470,10 +479,15 @@ class Databases extends Action $index->getId(), $index->setAttribute('status', 'stuck') ); + + // TODO: Send non DatabaseExceptions to Sentry ? + throw $e; + } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); } + // Do we want this in finally? $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } From 19667f78a92e00fa203a7a35bd4f4f13e2175851 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 7 Nov 2024 17:23:46 +0200 Subject: [PATCH 008/340] Add try catch on delete Attribute --- src/Appwrite/Platform/Workers/Databases.php | 180 ++++++++++---------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 1974a0b959..388dd3b88c 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -251,115 +251,118 @@ class Databases extends Action // - stuck: attribute was available but cannot be removed try { - if ($status !== 'failed') { - if ($type === Database::VAR_RELATIONSHIP) { - if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { - throw new DatabaseException('Collection not found'); + try { + if ($status !== 'failed') { + if ($type === Database::VAR_RELATIONSHIP) { + if ($options['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new DatabaseException('Collection not found'); + } + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); - } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); - throw new DatabaseException('Failed to delete Relationship'); + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); + throw new DatabaseException('Failed to delete Relationship'); + } + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + throw new DatabaseException('Failed to delete Attribute'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - throw new DatabaseException('Failed to delete Attribute'); } - } - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $dbForProject->deleteDocument('attributes', $attribute->getId()); - if (!$relatedAttribute->isEmpty()) { - $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); - } - } catch (\Throwable $e) { - Console::error($e->getMessage()); - - if ($e instanceof DatabaseException) { - $attribute->setAttribute('error', $e->getMessage()); if (!$relatedAttribute->isEmpty()) { - $relatedAttribute->setAttribute('error', $e->getMessage()); + $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); + } + } catch (\Throwable $e) { + Console::error($e->getMessage()); + + if ($e instanceof DatabaseException) { + $attribute->setAttribute('error', $e->getMessage()); + if (!$relatedAttribute->isEmpty()) { + $relatedAttribute->setAttribute('error', $e->getMessage()); + } } - } - $dbForProject->updateDocument( - 'attributes', - $attribute->getId(), - $attribute->setAttribute('status', 'stuck') - ); - if (!$relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', - $relatedAttribute->getId(), - $relatedAttribute->setAttribute('status', 'stuck') + $attribute->getId(), + $attribute->setAttribute('status', 'stuck') ); + if (!$relatedAttribute->isEmpty()) { + $dbForProject->updateDocument( + 'attributes', + $relatedAttribute->getId(), + $relatedAttribute->setAttribute('status', 'stuck') + ); + } + + // TODO: Send non DatabaseExceptions to Sentry + throw $e; + } finally { + $this->trigger($database, $collection, $attribute, $project, $projectId, $events); } - // TODO: Send non DatabaseExceptions to Sentry - throw $e; - } finally { - $this->trigger($database, $collection, $attribute, $project, $projectId, $events); - } + // The underlying database removes/rebuilds indexes when attribute is removed + // Update indexes table with changes + /** @var Document[] $indexes */ + $indexes = $collection->getAttribute('indexes', []); - // The underlying database removes/rebuilds indexes when attribute is removed - // Update indexes table with changes - /** @var Document[] $indexes */ - $indexes = $collection->getAttribute('indexes', []); + foreach ($indexes as $index) { + /** @var string[] $attributes */ + $attributes = $index->getAttribute('attributes'); + $lengths = $index->getAttribute('lengths'); + $orders = $index->getAttribute('orders'); - foreach ($indexes as $index) { - /** @var string[] $attributes */ - $attributes = $index->getAttribute('attributes'); - $lengths = $index->getAttribute('lengths'); - $orders = $index->getAttribute('orders'); + $found = \array_search($key, $attributes); - $found = \array_search($key, $attributes); + if ($found !== false) { + // If found, remove entry from attributes, lengths, and orders + // array_values wraps array_diff to reindex array keys + // when found attribute is removed from array + $attributes = \array_values(\array_diff($attributes, [$attributes[$found]])); + $lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : [])); + $orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : [])); - if ($found !== false) { - // If found, remove entry from attributes, lengths, and orders - // array_values wraps array_diff to reindex array keys - // when found attribute is removed from array - $attributes = \array_values(\array_diff($attributes, [$attributes[$found]])); - $lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : [])); - $orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : [])); - - if (empty($attributes)) { - $dbForProject->deleteDocument('indexes', $index->getId()); - } else { - $index - ->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN) - ->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN) - ->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN); - - // Check if an index exists with the same attributes and orders - $exists = false; - foreach ($indexes as $existing) { - if ( - $existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself - && $existing->getAttribute('attributes') === $index->getAttribute('attributes') - && $existing->getAttribute('orders') === $index->getAttribute('orders') - ) { - $exists = true; - break; - } - } - - if ($exists) { // Delete the duplicate if created, else update in db - $this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject); + if (empty($attributes)) { + $dbForProject->deleteDocument('indexes', $index->getId()); } else { - $dbForProject->updateDocument('indexes', $index->getId(), $index); + $index + ->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN) + ->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN) + ->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN); + + // Check if an index exists with the same attributes and orders + $exists = false; + foreach ($indexes as $existing) { + if ( + $existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself + && $existing->getAttribute('attributes') === $index->getAttribute('attributes') + && $existing->getAttribute('orders') === $index->getAttribute('orders') + ) { + $exists = true; + break; + } + } + + if ($exists) { // Delete the duplicate if created, else update in db + $this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject); + } else { + $dbForProject->updateDocument('indexes', $index->getId(), $index); + } } } } - } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + } finally { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + } } } @@ -480,15 +483,12 @@ class Databases extends Action $index->setAttribute('status', 'stuck') ); - // TODO: Send non DatabaseExceptions to Sentry ? throw $e; } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } - - // Do we want this in finally? - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } /** From cd0d1d94dbb56936091d07cd380180e4b857562d Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 7 Nov 2024 17:27:56 +0200 Subject: [PATCH 009/340] Add to finally --- src/Appwrite/Platform/Workers/Databases.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 388dd3b88c..8c26ca6cea 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -197,13 +197,12 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); - } + if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + } - if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } - - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** @@ -426,9 +425,9 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** From fb40970eba10f55596db980d89f0e1598d71ab43 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 7 Nov 2024 17:35:03 +0200 Subject: [PATCH 010/340] line --- src/Appwrite/Platform/Workers/Databases.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 8c26ca6cea..01f73018f4 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -197,6 +197,7 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); + if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } From 06274764c645a7678e071fc17fa8512b4e206a75 Mon Sep 17 00:00:00 2001 From: fogelito Date: Fri, 8 Nov 2024 07:12:23 +0200 Subject: [PATCH 011/340] Remove extra lines --- src/Appwrite/Platform/Workers/Databases.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 01f73018f4..7cff9f264a 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -354,7 +354,6 @@ class Databases extends Action } } } - } finally { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); @@ -410,10 +409,14 @@ class Databases extends Action } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); } catch (\Throwable $e) { - Console::error($e->getMessage()); - + Console::error('shmuel::createIndex'); if ($e instanceof DatabaseException) { + Console::error('shmuel::createIndex' . $e->getMessage()); + Console::error('shmuel::createIndex' . $e->getMessage()); + Console::error('shmuel::createIndex' . $e->getMessage()); + Console::error('shmuel::createIndex' . $e->getMessage()); + Console::error('shmuel::createIndex' . $e->getMessage()); $index->setAttribute('error', $e->getMessage()); } $dbForProject->updateDocument( @@ -428,7 +431,6 @@ class Databases extends Action $this->trigger($database, $collection, $index, $project, $projectId, $events); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } - } /** From e5730506ebf5c8f8cda94434d89b3d9013c0b66d Mon Sep 17 00:00:00 2001 From: fogelito Date: Sun, 10 Nov 2024 16:37:44 +0200 Subject: [PATCH 012/340] Remove var dumps --- src/Appwrite/Platform/Workers/Databases.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 7cff9f264a..accc003976 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -410,13 +410,7 @@ class Databases extends Action $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); } catch (\Throwable $e) { Console::error($e->getMessage()); - Console::error('shmuel::createIndex'); if ($e instanceof DatabaseException) { - Console::error('shmuel::createIndex' . $e->getMessage()); - Console::error('shmuel::createIndex' . $e->getMessage()); - Console::error('shmuel::createIndex' . $e->getMessage()); - Console::error('shmuel::createIndex' . $e->getMessage()); - Console::error('shmuel::createIndex' . $e->getMessage()); $index->setAttribute('error', $e->getMessage()); } $dbForProject->updateDocument( From d9e2ecff54fba52489e393ea5168a1d908d968f8 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 11 Nov 2024 16:45:17 +0900 Subject: [PATCH 013/340] Remove get document from worker --- src/Appwrite/Platform/Workers/Migrations.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index d430d0eb67..4b1926ed26 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -268,8 +268,6 @@ class Migrations extends Action $transfer = $source = $destination = null; try { - $migration = $this->dbForProject->getDocument('migrations', $migration->getId()); - if ( $migration->getAttribute('source') === SourceAppwrite::getName() && empty($migration->getAttribute('credentials', [])) From bae6e465fa564e1be53b4adfca59cc13b2a4e3ba Mon Sep 17 00:00:00 2001 From: fogelito Date: Mon, 11 Nov 2024 18:46:47 +0200 Subject: [PATCH 014/340] updateAttributes --- app/controllers/api/databases.php | 38 ++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 0114fd343c..6af4f592d6 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -396,20 +396,37 @@ function updateAttribute( } } - if (!empty($newKey) && $key !== $newKey) { - // Delete attribute and recreate since we can't modify IDs - $original = clone $attribute; + $purge = false; - $dbForProject->deleteDocument('attributes', $attribute->getId()); + if (!empty($newKey) && $key !== $newKey) { + $originalUid = $attribute->getId(); $attribute ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) ->setAttribute('key', $newKey); - try { - $attribute = $dbForProject->createDocument('attributes', $attribute); - } catch (DatabaseException|PDOException) { - $attribute = $dbForProject->createDocument('attributes', $original); + $dbForProject->updateDocument('attributes', $originalUid, $attribute); + + /** + * @var Document $index + */ + foreach ($collection->getAttribute('indexes') as $index) { + /** + * @var string[] $attributes + */ + $attributes = $index->getAttribute('attributes', []); + $found = \array_search($key, $attributes); + + var_dump($attributes); + var_dump('found==='); + var_dump($found); + + if ($found !== false) { + $attributes[$found] = $newKey; + $index->setAttribute('attributes', $attributes); + $dbForProject->updateDocument('indexes', $index->getId(), $index); + $purge = true; + } } } else { $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); @@ -417,6 +434,11 @@ function updateAttribute( $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + if($purge){ + // I think we are missing this? + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + } + $queueForEvents ->setContext('collection', $collection) ->setContext('database', $db) From 8cca88f2b8180944e0fb2a8170d431047de0805c Mon Sep 17 00:00:00 2001 From: fogelito Date: Mon, 11 Nov 2024 18:52:15 +0200 Subject: [PATCH 015/340] Remove Sentry comment --- src/Appwrite/Platform/Workers/Databases.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index accc003976..fe81114ea0 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -193,7 +193,6 @@ class Databases extends Action ); } - // TODO: Send non DatabaseExceptions to Sentry throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); @@ -298,7 +297,6 @@ class Databases extends Action ); } - // TODO: Send non DatabaseExceptions to Sentry throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); @@ -419,7 +417,6 @@ class Databases extends Action $index->setAttribute('status', 'failed') ); - // TODO: Send non DatabaseExceptions to Sentry throw $e; } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); From b62640489dde923fbe2cecf92a20bd59a062c44a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 12 Nov 2024 11:29:19 +0900 Subject: [PATCH 016/340] Fire logs for each individual migration error --- src/Appwrite/Platform/Workers/Migrations.php | 54 +++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 4b1926ed26..91056d5a49 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -17,6 +17,7 @@ use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Logger\Log; +use Utopia\Logger\Logger; use Utopia\Migration\Destination; use Utopia\Migration\Destinations\Appwrite as DestinationAppwrite; use Utopia\Migration\Exception as MigrationException; @@ -28,6 +29,7 @@ use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Transfer; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\System\System; class Migrations extends Action { @@ -37,6 +39,8 @@ class Migrations extends Action protected Document $project; + protected Logger $logger; + public static function getName(): string { return 'migrations'; @@ -53,13 +57,14 @@ class Migrations extends Action ->inject('dbForProject') ->inject('dbForConsole') ->inject('log') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log) => $this->action($message, $dbForProject, $dbForConsole, $log)); + ->inject('logger') + ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log, Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $log, $logger)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log): void + public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log, Logger $logger): void { $payload = $message->getPayload() ?? []; @@ -78,6 +83,7 @@ class Migrations extends Action $this->dbForProject = $dbForProject; $this->dbForConsole = $dbForConsole; $this->project = $project; + $this->logger = $logger; /** * Handle Event execution. @@ -324,7 +330,6 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - /** @var $sourceErrors $error */ $message = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message: '{$error->getMessage()}'"; if ($error->getPrevious()) { $message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine(); @@ -359,7 +364,6 @@ class Migrations extends Action if (! $migration->isEmpty()) { $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); - $migration->setAttribute('errors', [$th->getMessage()]); return; } @@ -379,7 +383,6 @@ class Migrations extends Action } $migration->setAttribute('errors', $errorMessages); - $log->addTag('migrationErrors', json_encode($errorMessages)); } } finally { if (! $tempAPIKey->isEmpty()) { @@ -394,7 +397,13 @@ class Migrations extends Action $destination->error(); $source->error(); - throw new Exception('Migration failed'); + foreach ($source->getErrors() as $error) { + $this->triggerExceptionLog($migration, $error); + } + + foreach ($destination->getErrors() as $error) { + $this->triggerExceptionLog($migration, $error); + } } if ($migration->getAttribute('status', '') === 'completed') { @@ -403,4 +412,37 @@ class Migrations extends Action } } } + + public function triggerExceptionLog(Document $migration, MigrationException $error) { + if (empty($this->logger)) { + return; + } + + $log = new Log(); + + $log->setNamespace("appwrite-worker"); + $log->setServer(\gethostname()); + $log->setVersion(System::getEnv('_APP_VERSION', 'UNKNOWN')); + $log->setType(Log::TYPE_ERROR); + $log->setMessage($error->getMessage()); + $log->setAction('appwrite-queue-' . Self::getName()); + $log->addTag('verboseType', get_class($error)); + $log->addTag('projectId', $this->project->getId() ?? 'n/a'); + $log->addExtra('file', $error->getFile()); + $log->addExtra('line', $error->getLine()); + $log->addExtra('trace', $error->getTraceAsString()); + $log->addExtra('migrationId', $migration->getId() ?? 'n/a'); + $log->addExtra('source', $migration->getAttribute('source') ?? 'n/a'); + $log->addExtra('resourceName', $error->getResourceName()); + $log->addExtra('resourceGroup', $error->getResourceGroup()); + $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; + $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); + + try { + $responseCode = $this->logger->addLog($log); + Console::info('Error log pushed with status code: ' . $responseCode); + } catch (\Throwable $th) { + Console::error('Error pushing log: ' . $th->getMessage()); + } + } } From a460a41fe56ca2a5ed893bfae62e9580ae10d264 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 12 Nov 2024 11:33:13 +0900 Subject: [PATCH 017/340] Run Linter --- src/Appwrite/Platform/Workers/Migrations.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 91056d5a49..770caa2e69 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -413,7 +413,8 @@ class Migrations extends Action } } - public function triggerExceptionLog(Document $migration, MigrationException $error) { + public function triggerExceptionLog(Document $migration, MigrationException $error) + { if (empty($this->logger)) { return; } @@ -425,7 +426,7 @@ class Migrations extends Action $log->setVersion(System::getEnv('_APP_VERSION', 'UNKNOWN')); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); - $log->setAction('appwrite-queue-' . Self::getName()); + $log->setAction('appwrite-queue-' . self::getName()); $log->addTag('verboseType', get_class($error)); $log->addTag('projectId', $this->project->getId() ?? 'n/a'); $log->addExtra('file', $error->getFile()); @@ -444,5 +445,5 @@ class Migrations extends Action } catch (\Throwable $th) { Console::error('Error pushing log: ' . $th->getMessage()); } - } + } } From 1337ea77b1cb764e8e4cc81a45b16129d306e910 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 12 Nov 2024 16:18:09 +0900 Subject: [PATCH 018/340] Fix Optionals --- src/Appwrite/Platform/Workers/Migrations.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 770caa2e69..921d6dc69a 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -39,7 +39,7 @@ class Migrations extends Action protected Document $project; - protected Logger $logger; + protected ?Logger $logger; public static function getName(): string { @@ -58,13 +58,13 @@ class Migrations extends Action ->inject('dbForConsole') ->inject('log') ->inject('logger') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log, Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $log, $logger)); + ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log, ?Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $log, $logger)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log, Logger $logger): void + public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log, ?Logger $logger): void { $payload = $message->getPayload() ?? []; From 7f3a3429404bef32e5884ac38552834fe032ade6 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Tue, 12 Nov 2024 16:44:20 +0000 Subject: [PATCH 019/340] Remove inaccurate info about leaving the URL parameter empty --- docs/references/account/create-token-magic-url.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/account/create-token-magic-url.md b/docs/references/account/create-token-magic-url.md index 6ebe4154b8..99ad6dba5e 100644 --- a/docs/references/account/create-token-magic-url.md +++ b/docs/references/account/create-token-magic-url.md @@ -1,3 +1,3 @@ -Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST /v1/account/sessions/token](https://appwrite.io/docs/references/cloud/client-web/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default. +Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST /v1/account/sessions/token](https://appwrite.io/docs/references/cloud/client-web/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. A user is limited to 10 active sessions at a time by default. [Learn more about session limits](https://appwrite.io/docs/authentication-security#limits). From 29e7d1f7d07719c580be7a7c2d71912e492b61fe Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 13 Nov 2024 09:13:00 +0900 Subject: [PATCH 020/340] Address Comments --- src/Appwrite/Platform/Workers/Migrations.php | 21 +++++++------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 921d6dc69a..2514c73d6a 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -56,15 +56,14 @@ class Migrations extends Action ->inject('message') ->inject('dbForProject') ->inject('dbForConsole') - ->inject('log') ->inject('logger') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log, ?Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $log, $logger)); + ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, ?Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $logger)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log, ?Logger $logger): void + public function action(Message $message, Database $dbForProject, Database $dbForConsole, ?Logger $logger): void { $payload = $message->getPayload() ?? []; @@ -92,10 +91,7 @@ class Migrations extends Action return; } - $log->addTag('migrationId', $migration->getId()); - $log->addTag('projectId', $project->getId()); - - $this->processMigration($migration, $log); + $this->processMigration($migration); } /** @@ -265,7 +261,7 @@ class Migrations extends Action * @throws \Utopia\Database\Exception * @throws Exception */ - protected function processMigration(Document $migration, Log $log): void + protected function processMigration(Document $migration): void { $project = $this->project; $projectDocument = $this->dbForConsole->getDocument('projects', $project->getId()); @@ -291,8 +287,6 @@ class Migrations extends Action $migration->setAttribute('status', 'processing'); $this->updateMigrationDocument($migration, $projectDocument); - $log->addTag('type', $migration->getAttribute('source')); - $source = $this->processSource($migration); $destination = $this->processDestination($migration, $tempAPIKey->getAttribute('secret')); @@ -349,7 +343,6 @@ class Migrations extends Action } $migration->setAttribute('errors', $errorMessages); - $log->addExtra('migrationErrors', json_encode($errorMessages)); $this->updateMigrationDocument($migration, $projectDocument); return; @@ -428,12 +421,12 @@ class Migrations extends Action $log->setMessage($error->getMessage()); $log->setAction('appwrite-queue-' . self::getName()); $log->addTag('verboseType', get_class($error)); - $log->addTag('projectId', $this->project->getId() ?? 'n/a'); + $log->addTag('projectId', $this->project->getId() ?? ''); $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('migrationId', $migration->getId() ?? 'n/a'); - $log->addExtra('source', $migration->getAttribute('source') ?? 'n/a'); + $log->addExtra('migrationId', $migration->getId() ?? ''); + $log->addExtra('source', $migration->getAttribute('source') ?? ''); $log->addExtra('resourceName', $error->getResourceName()); $log->addExtra('resourceGroup', $error->getResourceGroup()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; From 91cc0e627aca1372a3ca1493cbe97a9ec4a489b2 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 13 Nov 2024 10:29:43 +0900 Subject: [PATCH 021/340] Address Comments --- app/worker.php | 44 +++++++++++++++ src/Appwrite/Platform/Workers/Migrations.php | 58 ++++++-------------- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/app/worker.php b/app/worker.php index 4741afe7ea..6d55bdb2d3 100644 --- a/app/worker.php +++ b/app/worker.php @@ -277,6 +277,50 @@ Server::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); +Server::setResource('logError', function (Registry $register, Document $project) { + return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) { + $logger = $register->get('logger'); + + if ($logger) { + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); + + $log = new Log(); + $log->setNamespace($namespace); + $log->setServer(\gethostname()); + $log->setVersion($version); + $log->setType(Log::TYPE_ERROR); + $log->setMessage($error->getMessage()); + + $log->addTag('code', $error->getCode()); + $log->addTag('verboseType', get_class($error)); + $log->addTag('projectId', $project->getId() ?? ''); + + $log->addExtra('file', $error->getFile()); + $log->addExtra('line', $error->getLine()); + $log->addExtra('trace', $error->getTraceAsString()); + + + foreach ($extras as $key => $value) { + $log->addExtra($key, $value); + } + + $log->setAction($action); + + $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; + $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); + + try { + $responseCode = $logger->addLog($log); + Console::info('Error log pushed with status code: ' . $responseCode); + } catch (Throwable $th) { + Console::error('Error pushing log: ' . $th->getMessage()); + } + } + + Console::warning("Failed: {$error->getMessage()}"); + Console::warning($error->getTraceAsString()); + }; +}, ['register', 'project']); $pools = $register->get('pools'); $platform = new Appwrite(); diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 2514c73d6a..6aa3b08211 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -39,7 +39,7 @@ class Migrations extends Action protected Document $project; - protected ?Logger $logger; + protected $logError; public static function getName(): string { @@ -56,14 +56,14 @@ class Migrations extends Action ->inject('message') ->inject('dbForProject') ->inject('dbForConsole') - ->inject('logger') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, ?Logger $logger) => $this->action($message, $dbForProject, $dbForConsole, $logger)); + ->inject('logError') + ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, callable $logError) => $this->action($message, $dbForProject, $dbForConsole, $logError)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, ?Logger $logger): void + public function action(Message $message, Database $dbForProject, Database $dbForConsole, callable $logError): void { $payload = $message->getPayload() ?? []; @@ -82,7 +82,7 @@ class Migrations extends Action $this->dbForProject = $dbForProject; $this->dbForConsole = $dbForConsole; $this->project = $project; - $this->logger = $logger; + $this->logError = $logError; /** * Handle Event execution. @@ -391,11 +391,21 @@ class Migrations extends Action $source->error(); foreach ($source->getErrors() as $error) { - $this->triggerExceptionLog($migration, $error); + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId() ?? '', + 'source' => $migration->getAttribute('source') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); } foreach ($destination->getErrors() as $error) { - $this->triggerExceptionLog($migration, $error); + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId() ?? '', + 'source' => $migration->getAttribute('source') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); } } @@ -405,38 +415,4 @@ class Migrations extends Action } } } - - public function triggerExceptionLog(Document $migration, MigrationException $error) - { - if (empty($this->logger)) { - return; - } - - $log = new Log(); - - $log->setNamespace("appwrite-worker"); - $log->setServer(\gethostname()); - $log->setVersion(System::getEnv('_APP_VERSION', 'UNKNOWN')); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($error->getMessage()); - $log->setAction('appwrite-queue-' . self::getName()); - $log->addTag('verboseType', get_class($error)); - $log->addTag('projectId', $this->project->getId() ?? ''); - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('migrationId', $migration->getId() ?? ''); - $log->addExtra('source', $migration->getAttribute('source') ?? ''); - $log->addExtra('resourceName', $error->getResourceName()); - $log->addExtra('resourceGroup', $error->getResourceGroup()); - $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - try { - $responseCode = $this->logger->addLog($log); - Console::info('Error log pushed with status code: ' . $responseCode); - } catch (\Throwable $th) { - Console::error('Error pushing log: ' . $th->getMessage()); - } - } } From 54db5655a15b362a51266cc6f595dcad930d6986 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 13 Nov 2024 13:42:49 +0900 Subject: [PATCH 022/340] Run Linter --- app/worker.php | 2 +- src/Appwrite/Platform/Workers/Migrations.php | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/worker.php b/app/worker.php index 6d55bdb2d3..6b7aba5c1b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -298,7 +298,7 @@ Server::setResource('logError', function (Registry $register, Document $project) $log->addExtra('file', $error->getFile()); $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); - + foreach ($extras as $key => $value) { $log->addExtra($key, $value); diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 6aa3b08211..fdd885effa 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -16,8 +16,6 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; -use Utopia\Logger\Log; -use Utopia\Logger\Logger; use Utopia\Migration\Destination; use Utopia\Migration\Destinations\Appwrite as DestinationAppwrite; use Utopia\Migration\Exception as MigrationException; @@ -29,7 +27,6 @@ use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Transfer; use Utopia\Platform\Action; use Utopia\Queue\Message; -use Utopia\System\System; class Migrations extends Action { From ca533f40c97f8daf2056a958ce6cf835f3cf7466 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:45:50 +0100 Subject: [PATCH 023/340] fix: memberships-privacy mfa only --- app/controllers/api/teams.php | 11 +++++-- .../Services/Teams/TeamsCustomClientTest.php | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index be055f0935..ba1858c5aa 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -805,8 +805,11 @@ App::get('/v1/teams/:teamId/memberships') }, $membershipsPrivacy); $memberships = array_map(function ($membership) use ($dbForProject, $team, $membershipsPrivacy) { + $user = !empty(array_filter($membershipsPrivacy)) + ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) + : new Document(); + if ($membershipsPrivacy['mfa']) { - $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); $mfa = $user->getAttribute('mfa', false); if ($mfa) { @@ -888,9 +891,11 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') return $privacy || $isPrivilegedUser || $isAppUser; }, $membershipsPrivacy); - if ($membershipsPrivacy['mfa']) { - $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); + $user = !empty(array_filter($membershipsPrivacy)) + ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) + : new Document(); + if ($membershipsPrivacy['mfa']) { $mfa = $user->getAttribute('mfa', false); if ($mfa) { diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index 03cb1983f1..7286bb0827 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -83,6 +83,38 @@ class TeamsCustomClientTest extends Scope $this->assertNotEmpty($response['body']['memberships'][0]['userName']); $this->assertNotEmpty($response['body']['memberships'][0]['userEmail']); $this->assertArrayHasKey('mfa', $response['body']['memberships'][0]); + + /** + * Update project settings to show only MFA + */ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/auth/memberships-privacy', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), [ + 'userName' => false, + 'userEmail' => false, + 'mfa' => true, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + /** + * Test that sensitive fields are not shown + */ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['total']); + $this->assertNotEmpty($response['body']['memberships'][0]['$id']); + + // Assert that sensitive fields are present + $this->assertEmpty($response['body']['memberships'][0]['userName']); + $this->assertEmpty($response['body']['memberships'][0]['userEmail']); + $this->assertArrayHasKey('mfa', $response['body']['memberships'][0]); } /** From 8124f6998ec3d7004da9faf6ac1b674810f95d25 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Tue, 12 Nov 2024 10:45:00 +0100 Subject: [PATCH 024/340] feat: add telemetry --- app/realtime.php | 22 +- composer.json | 13 +- composer.lock | 2082 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 1834 insertions(+), 283 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index 48979817c4..15635058cf 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -29,6 +29,7 @@ use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\System\System; +use Utopia\Telemetry\Adapter\None as NoTelemetry; use Utopia\WebSocket\Adapter; use Utopia\WebSocket\Server; @@ -142,6 +143,13 @@ if (!function_exists('getRealtime')) { } } +if (!function_exists('getTelemetry')) { + function getTelemetry(int $workerId): Utopia\Telemetry\Adapter + { + return new NoTelemetry(); + } +} + $realtime = getRealtime(); /** @@ -274,6 +282,12 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) { Console::success('Worker ' . $workerId . ' started successfully'); + $telemetry = getTelemetry($workerId); + $register->set('telemetry', fn () => $telemetry); + $register->set('telemetry.connectionCounter', fn () => $telemetry->createUpDownCounter('realtime.server.open_connections')); + $register->set('telemetry.connectionCreatedCounter', fn () => $telemetry->createCounter('realtime.server.connection.created')); + $register->set('telemetry.messageSentCounter', fn () => $telemetry->createCounter('realtime.server.message.sent')); + $attempts = 0; $start = time(); @@ -416,6 +430,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, ); if (($num = count($receivers)) > 0) { + $register->get('telemetry.messageSentCounter')->add($num); $stats->incr($event['project'], 'messages', $num); } }); @@ -519,6 +534,9 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, ] ])); + $register->get('telemetry.connectionCounter')->add(1); + $register->get('telemetry.connectionCreatedCounter')->add(1); + $stats->set($project->getId(), [ 'projectId' => $project->getId(), 'teamId' => $project->getAttribute('teamId') @@ -655,12 +673,14 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re } }); -$server->onClose(function (int $connection) use ($realtime, $stats) { +$server->onClose(function (int $connection) use ($realtime, $stats, $register) { if (array_key_exists($connection, $realtime->connections)) { $stats->decr($realtime->connections[$connection]['projectId'], 'connectionsTotal'); } $realtime->unsubscribe($connection); + $register->get('telemetry.connectionCounter')->add(-1); + Console::info('Connection close: ' . $connection); }); diff --git a/composer.json b/composer.json index a04ca51d43..708a0e98b0 100644 --- a/composer.json +++ b/composer.json @@ -70,6 +70,7 @@ "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", "utopia-php/system": "0.9.*", + "utopia-php/telemetry": "dev-initial-commit", "utopia-php/vcs": "0.8.*", "utopia-php/websocket": "0.1.*", "matomo/device-detector": "6.1.*", @@ -96,6 +97,16 @@ "config": { "platform": { "php": "8.3" + }, + "allow-plugins": { + "php-http/discovery": false, + "tbachert/spi": false } - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/utopia-php/telemetry" + } + ] } diff --git a/composer.lock b/composer.lock index 691a7e740e..48baa1e485 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": "b358198535c1867eabed7c0f99135a57", + "content-hash": "2f4d6d3242be92cb63e0668c2dbc5b61", "packages": [ { "name": "adhocore/jwt", @@ -277,6 +277,66 @@ }, "time": "2024-07-15T13:18:35+00:00" }, + { + "name": "brick/math", + "version": "0.12.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.12.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-11-29T23:19:16+00:00" + }, { "name": "chillerlan/php-qrcode", "version": "4.3.4", @@ -422,6 +482,87 @@ ], "time": "2024-07-17T01:04:28+00:00" }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.3.2", @@ -566,6 +707,50 @@ }, "time": "2024-05-03T06:31:11+00:00" }, + { + "name": "google/protobuf", + "version": "v4.28.3", + "source": { + "type": "git", + "url": "https://github.com/protocolbuffers/protobuf-php.git", + "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c5c311e0f3d89928251ac5a2f0e3db283612c100", + "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": ">=5.0.0" + }, + "suggest": { + "ext-bcmath": "Need to support JSON deserialization" + }, + "type": "library", + "autoload": { + "psr-4": { + "Google\\Protobuf\\": "src/Google/Protobuf", + "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "proto library for PHP", + "homepage": "https://developers.google.com/protocol-buffers/", + "keywords": [ + "proto" + ], + "support": { + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.28.3" + }, + "time": "2024-10-22T22:27:17+00:00" + }, { "name": "jean85/pretty-package-versions", "version": "2.0.6", @@ -906,6 +1091,553 @@ }, "time": "2019-09-10T13:16:29+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2024-09-09T07:06:30+00:00" + }, + { + "name": "nyholm/psr7-server", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7-server.git", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/4335801d851f554ca43fa6e7d2602141538854dc", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "nyholm/nsa": "^1.1", + "nyholm/psr7": "^1.3", + "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "Helper classes to handle PSR-7 server requests", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7-server/issues", + "source": "https://github.com/Nyholm/psr7-server/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2023-11-08T09:30:43+00:00" + }, + { + "name": "open-telemetry/api", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/api.git", + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", + "shasum": "" + }, + "require": { + "open-telemetry/context": "^1.0", + "php": "^8.1", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/polyfill-php82": "^1.26" + }, + "conflict": { + "open-telemetry/sdk": "<=1.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1.x-dev" + }, + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + } + }, + "autoload": { + "files": [ + "Trace/functions.php" + ], + "psr-4": { + "OpenTelemetry\\API\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "API for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "api", + "apm", + "logging", + "opentelemetry", + "otel", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/context", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/context.git", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "shasum": "" + }, + "require": { + "php": "^8.1", + "symfony/polyfill-php82": "^1.26" + }, + "suggest": { + "ext-ffi": "To allow context switching in Fibers" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "fiber/initialize_fiber_handler.php" + ], + "psr-4": { + "OpenTelemetry\\Context\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Context implementation for OpenTelemetry PHP.", + "keywords": [ + "Context", + "opentelemetry", + "otel" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-08-21T00:29:20+00:00" + }, + { + "name": "open-telemetry/exporter-otlp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/exporter-otlp.git", + "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/9b6de12204f25f8ab9540b46d6e7b5151897ce18", + "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18", + "shasum": "" + }, + "require": { + "open-telemetry/api": "^1.0", + "open-telemetry/gen-otlp-protobuf": "^1.1", + "open-telemetry/sdk": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "_register.php" + ], + "psr-4": { + "OpenTelemetry\\Contrib\\Otlp\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "OTLP exporter for OpenTelemetry.", + "keywords": [ + "Metrics", + "exporter", + "gRPC", + "http", + "opentelemetry", + "otel", + "otlp", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/gen-otlp-protobuf", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "shasum": "" + }, + "require": { + "google/protobuf": "^3.22 || ^4.0", + "php": "^8.0" + }, + "suggest": { + "ext-protobuf": "For better performance, when dealing with the protobuf format" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opentelemetry\\Proto\\": "Opentelemetry/Proto/", + "GPBMetadata\\Opentelemetry\\": "GPBMetadata/Opentelemetry/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "PHP protobuf files for communication with OpenTelemetry OTLP collectors/servers.", + "keywords": [ + "Metrics", + "apm", + "gRPC", + "logging", + "opentelemetry", + "otel", + "otlp", + "protobuf", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-10-30T11:49:49+00:00" + }, + { + "name": "open-telemetry/sdk", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sdk.git", + "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/fb0ff8d8279a3776bd604791e2531dd0cc147e8b", + "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nyholm/psr7-server": "^1.1", + "open-telemetry/api": "~1.0 || ~1.1", + "open-telemetry/context": "^1.0", + "open-telemetry/sem-conv": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14", + "psr/http-client": "^1.0", + "psr/http-client-implementation": "^1.0", + "psr/http-factory-implementation": "^1.0", + "psr/http-message": "^1.0.1|^2.0", + "psr/log": "^1.1|^2.0|^3.0", + "ramsey/uuid": "^3.0 || ^4.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php82": "^1.26", + "tbachert/spi": "^1.0.1" + }, + "suggest": { + "ext-gmp": "To support unlimited number of synchronous metric readers", + "ext-mbstring": "To increase performance of string operations", + "open-telemetry/sdk-configuration": "File-based OpenTelemetry SDK configuration" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + }, + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + } + }, + "autoload": { + "files": [ + "Common/Util/functions.php", + "Logs/Exporter/_register.php", + "Metrics/MetricExporter/_register.php", + "Propagation/_register.php", + "Trace/SpanExporter/_register.php", + "Common/Dev/Compatibility/_load.php", + "_autoload.php" + ], + "psr-4": { + "OpenTelemetry\\SDK\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "SDK for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "sdk", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/sem-conv", + "version": "1.27.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sem-conv.git", + "reference": "1dba705fea74bc0718d04be26090e3697e56f4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/1dba705fea74bc0718d04be26090e3697e56f4e6", + "reference": "1dba705fea74bc0718d04be26090e3697e56f4e6", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenTelemetry\\SemConv\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Semantic conventions for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "semantic conventions", + "semconv", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-08-28T09:20:31+00:00" + }, { "name": "paragonie/constant_time_encoding", "version": "v2.7.0", @@ -973,6 +1705,85 @@ }, "time": "2024-05-08T12:18:48+00:00" }, + { + "name": "php-http/discovery", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.20.0" + }, + "time": "2024-10-02T11:20:13+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v6.9.1", @@ -1054,6 +1865,450 @@ ], "time": "2023-11-25T22:23:28+00:00" }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.6", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.6" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2024-04-27T21:32:50+00:00" + }, { "name": "spomky-labs/otphp", "version": "v10.0.3", @@ -1129,6 +2384,245 @@ }, "time": "2022-03-17T08:00:35+00:00" }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/http-client", + "version": "v7.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", + "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-05T16:45:54+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.31.0", @@ -1289,6 +2783,217 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php82", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php82.git", + "reference": "5d2ed36f7734637dacc025f179698031951b1692" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692", + "reference": "5d2ed36f7734637dacc025f179698031951b1692", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php82\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php82/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "tbachert/spi", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/Nevay/spi.git", + "reference": "2ddfaf815dafb45791a61b08170de8d583c16062" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nevay/spi/zipball/2ddfaf815dafb45791a61b08170de8d583c16062", + "reference": "2ddfaf815dafb45791a61b08170de8d583c16062", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "composer/semver": "^1.0 || ^2.0 || ^3.0", + "php": "^8.1" + }, + "require-dev": { + "composer/composer": "^2.0", + "infection/infection": "^0.27.9", + "phpunit/phpunit": "^10.5", + "psalm/phar": "^5.18" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-main": "0.2.x-dev" + }, + "class": "Nevay\\SPI\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Nevay\\SPI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Service provider loading facility", + "keywords": [ + "service provider" + ], + "support": { + "issues": "https://github.com/Nevay/spi/issues", + "source": "https://github.com/Nevay/spi/tree/v1.0.2" + }, + "time": "2024-10-04T16:36:12+00:00" + }, { "name": "thecodingmachine/safe", "version": "v2.5.0", @@ -2222,16 +3927,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.11", + "version": "0.6.12", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7" + "reference": "9a8c905af4cece5c5ec9542a5b534befce067260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", - "reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/9a8c905af4cece5c5ec9542a5b534befce067260", + "reference": "9a8c905af4cece5c5ec9542a5b534befce067260", "shasum": "" }, "require": { @@ -2272,9 +3977,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.11" + "source": "https://github.com/utopia-php/migration/tree/0.6.12" }, - "time": "2024-10-31T06:19:57+00:00" + "time": "2024-11-12T00:31:53+00:00" }, { "name": "utopia-php/mongo", @@ -2542,16 +4247,16 @@ }, { "name": "utopia-php/queue", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8" + "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/94c240d9f6383829807ce7b2d737f04b159fd3e8", - "reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/40fdd9799d0a11dd33fca06f8223032a47dce2f6", + "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6", "shasum": "" }, "require": { @@ -2597,9 +4302,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.7.1" + "source": "https://github.com/utopia-php/queue/tree/0.7.2" }, - "time": "2024-11-05T17:00:38+00:00" + "time": "2024-11-11T10:04:02+00:00" }, { "name": "utopia-php/registry", @@ -2816,17 +4521,83 @@ "time": "2024-10-09T14:44:01+00:00" }, { - "name": "utopia-php/vcs", - "version": "0.8.3", + "name": "utopia-php/telemetry", + "version": "dev-initial-commit", "source": { "type": "git", - "url": "https://github.com/utopia-php/vcs.git", - "reference": "a032ed0611a8f4467aeaa9484f73223074457337" + "url": "https://github.com/utopia-php/telemetry.git", + "reference": "a51fd18289921fc81f69d98e51f73ebb381eeeb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/a032ed0611a8f4467aeaa9484f73223074457337", - "reference": "a032ed0611a8f4467aeaa9484f73223074457337", + "url": "https://api.github.com/repos/utopia-php/telemetry/zipball/a51fd18289921fc81f69d98e51f73ebb381eeeb9", + "reference": "a51fd18289921fc81f69d98e51f73ebb381eeeb9", + "shasum": "" + }, + "require": { + "ext-opentelemetry": "*", + "ext-protobuf": "*", + "nyholm/psr7": "^1.8", + "open-telemetry/exporter-otlp": "^1.1", + "open-telemetry/sdk": "^1.1", + "php": ">=8.0", + "symfony/http-client": "^7.1" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "scripts": { + "lint": [ + "vendor/bin/pint --test" + ], + "format": [ + "vendor/bin/pint" + ], + "check": [ + "vendor/bin/phpstan analyse -c phpstan.neon" + ], + "test": [ + "vendor/bin/phpunit --configuration phpunit.xml" + ], + "bench": [ + "vendor/bin/phpbench run --report=benchmark" + ] + }, + "license": [ + "MIT" + ], + "keywords": [ + "framework", + "php", + "upf" + ], + "support": { + "source": "https://github.com/utopia-php/telemetry/tree/initial-commit", + "issues": "https://github.com/utopia-php/telemetry/issues" + }, + "time": "2024-11-11T17:36:02+00:00" + }, + { + "name": "utopia-php/vcs", + "version": "0.8.5", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/vcs.git", + "reference": "7622330628d53844a3873ca873338150756bab82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/7622330628d53844a3873ca873338150756bab82", + "reference": "7622330628d53844a3873ca873338150756bab82", "shasum": "" }, "require": { @@ -2860,9 +4631,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.8.3" + "source": "https://github.com/utopia-php/vcs/tree/0.8.5" }, - "time": "2024-11-05T17:10:09+00:00" + "time": "2024-11-11T18:33:10+00:00" }, { "name": "utopia-php/websocket", @@ -4758,109 +6529,6 @@ }, "time": "2021-02-03T23:26:27+00:00" }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -6013,73 +7681,6 @@ ], "time": "2024-11-05T15:34:55+00:00" }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/filesystem", "version": "v7.1.6", @@ -6652,89 +8253,6 @@ ], "time": "2024-11-06T09:25:12+00:00" }, - { - "name": "symfony/service-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/string", "version": "v7.1.6", @@ -6923,16 +8441,16 @@ }, { "name": "twig/twig", - "version": "v3.14.1", + "version": "v3.14.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "f405356d20fb43603bcadc8b09bfb676cb04a379" + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/f405356d20fb43603bcadc8b09bfb676cb04a379", - "reference": "f405356d20fb43603bcadc8b09bfb676cb04a379", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", "shasum": "" }, "require": { @@ -6986,7 +8504,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.1" + "source": "https://github.com/twigphp/Twig/tree/v3.14.2" }, "funding": [ { @@ -6998,7 +8516,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T18:17:38+00:00" + "time": "2024-11-07T12:36:22+00:00" }, { "name": "webmozart/glob", @@ -7052,7 +8570,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/telemetry": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From 1db71a46ea45a284e77ee695e21bd91e8082f968 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Wed, 13 Nov 2024 12:49:48 +0100 Subject: [PATCH 025/340] chore: use telemetry 0.1.0 --- composer.json | 10 +---- composer.lock | 110 +++++++++++++++++++++----------------------------- 2 files changed, 49 insertions(+), 71 deletions(-) diff --git a/composer.json b/composer.json index 708a0e98b0..99f696e116 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,7 @@ "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", "utopia-php/system": "0.9.*", - "utopia-php/telemetry": "dev-initial-commit", + "utopia-php/telemetry": "0.1.*", "utopia-php/vcs": "0.8.*", "utopia-php/websocket": "0.1.*", "matomo/device-detector": "6.1.*", @@ -102,11 +102,5 @@ "php-http/discovery": false, "tbachert/spi": false } - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/utopia-php/telemetry" - } - ] + } } diff --git a/composer.lock b/composer.lock index 48baa1e485..508de82034 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": "2f4d6d3242be92cb63e0668c2dbc5b61", + "content-hash": "c56db8736d679aff6e2b275ec59f1dbf", "packages": [ { "name": "adhocore/jwt", @@ -3677,21 +3677,22 @@ }, { "name": "utopia-php/framework", - "version": "0.33.11", + "version": "0.33.12", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "354ff0d23bfc6e82bea0fe8e89e115cff1af8466" + "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/354ff0d23bfc6e82bea0fe8e89e115cff1af8466", - "reference": "354ff0d23bfc6e82bea0fe8e89e115cff1af8466", + "url": "https://api.github.com/repos/utopia-php/http/zipball/bfb7812df9e489b3cba7d5504a49ce578c71af1f", + "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f", "shasum": "" }, "require": { - "php": ">=8.0", - "utopia-php/compression": "0.1.*" + "php": ">=8.1", + "utopia-php/compression": "0.1.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "^1.2", @@ -3717,9 +3718,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.11" + "source": "https://github.com/utopia-php/http/tree/0.33.12" }, - "time": "2024-11-08T18:47:43+00:00" + "time": "2024-11-13T12:45:45+00:00" }, { "name": "utopia-php/image", @@ -4247,22 +4248,23 @@ }, { "name": "utopia-php/queue", - "version": "0.7.2", + "version": "0.7.3", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6" + "reference": "16074a98ee7d6212bc1228de200e13db470c098a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/40fdd9799d0a11dd33fca06f8223032a47dce2f6", - "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/16074a98ee7d6212bc1228de200e13db470c098a", + "reference": "16074a98ee7d6212bc1228de200e13db470c098a", "shasum": "" }, "require": { - "php": ">=8.0", + "php": ">=8.1", "utopia-php/cli": "0.15.*", - "utopia-php/framework": "0.*.*" + "utopia-php/framework": "0.*.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "^0.2.3", @@ -4302,9 +4304,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.7.2" + "source": "https://github.com/utopia-php/queue/tree/0.7.3" }, - "time": "2024-11-11T10:04:02+00:00" + "time": "2024-11-13T12:47:48+00:00" }, { "name": "utopia-php/registry", @@ -4522,16 +4524,16 @@ }, { "name": "utopia-php/telemetry", - "version": "dev-initial-commit", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/telemetry.git", - "reference": "a51fd18289921fc81f69d98e51f73ebb381eeeb9" + "reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/telemetry/zipball/a51fd18289921fc81f69d98e51f73ebb381eeeb9", - "reference": "a51fd18289921fc81f69d98e51f73ebb381eeeb9", + "url": "https://api.github.com/repos/utopia-php/telemetry/zipball/d35f2f0632f4ee0be63fb7ace6a94a6adda71a80", + "reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80", "shasum": "" }, "require": { @@ -4555,23 +4557,7 @@ "Utopia\\": "src/" } }, - "scripts": { - "lint": [ - "vendor/bin/pint --test" - ], - "format": [ - "vendor/bin/pint" - ], - "check": [ - "vendor/bin/phpstan analyse -c phpstan.neon" - ], - "test": [ - "vendor/bin/phpunit --configuration phpunit.xml" - ], - "bench": [ - "vendor/bin/phpbench run --report=benchmark" - ] - }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4581,10 +4567,10 @@ "upf" ], "support": { - "source": "https://github.com/utopia-php/telemetry/tree/initial-commit", - "issues": "https://github.com/utopia-php/telemetry/issues" + "issues": "https://github.com/utopia-php/telemetry/issues", + "source": "https://github.com/utopia-php/telemetry/tree/0.1.0" }, - "time": "2024-11-11T17:36:02+00:00" + "time": "2024-11-13T10:29:53+00:00" }, { "name": "utopia-php/vcs", @@ -5822,16 +5808,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.5.1", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f" + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0c70d2c566e899666f367ab7b80986beb3581e6f", - "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c", + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c", "shasum": "" }, "require": { @@ -5840,7 +5826,7 @@ "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", "webmozart/assert": "^1.9.1" }, "require-dev": { @@ -5880,9 +5866,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.5.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.0" }, - "time": "2024-11-06T11:58:54+00:00" + "time": "2024-11-12T11:25:25+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -6013,30 +5999,30 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.33.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -6054,9 +6040,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" }, - "time": "2024-10-13T11:25:22+00:00" + "time": "2024-10-13T11:29:49+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8570,9 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/telemetry": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 71f2c6c1316eb041269409bc591ff5bc2201eaeb Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 13 Nov 2024 14:55:56 +0200 Subject: [PATCH 026/340] Remove purgeCachedCollection --- app/controllers/api/databases.php | 12 ------------ src/Appwrite/Platform/Workers/Databases.php | 2 -- 2 files changed, 14 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 6af4f592d6..523529698d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -396,8 +396,6 @@ function updateAttribute( } } - $purge = false; - if (!empty($newKey) && $key !== $newKey) { $originalUid = $attribute->getId(); @@ -417,15 +415,10 @@ function updateAttribute( $attributes = $index->getAttribute('attributes', []); $found = \array_search($key, $attributes); - var_dump($attributes); - var_dump('found==='); - var_dump($found); - if ($found !== false) { $attributes[$found] = $newKey; $index->setAttribute('attributes', $attributes); $dbForProject->updateDocument('indexes', $index->getId(), $index); - $purge = true; } } } else { @@ -434,11 +427,6 @@ function updateAttribute( $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); - if($purge){ - // I think we are missing this? - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); - } - $queueForEvents ->setContext('collection', $collection) ->setContext('database', $db) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index f697e7be13..1cbc3a3f8b 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -350,11 +350,9 @@ class Databases extends Action } $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } From 68e96e9851a9500a2b087e3bf48b97be1f898e0d Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 13 Nov 2024 18:32:20 +0200 Subject: [PATCH 027/340] comment --- app/controllers/api/databases.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 523529698d..f07a1e039d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2609,6 +2609,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); } + // todo: Think of a better solution $lengths[$i] = null; if ($attributeType === Database::VAR_STRING) { From 45f85d6b4d143a0c287c6f9b1c70eb40921a1d96 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:30:48 -0800 Subject: [PATCH 028/340] fix: remove duplicate dart-2.16 runtime template --- app/config/function-templates.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/function-templates.php b/app/config/function-templates.php index 762c33dd9a..fec9d2227f 100644 --- a/app/config/function-templates.php +++ b/app/config/function-templates.php @@ -11,7 +11,7 @@ const TEMPLATE_RUNTIMES = [ ], 'DART' => [ 'name' => 'dart', - 'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16', '2.16'] + 'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16'] ], 'GO' => [ 'name' => 'go', From 72e491ac69648c1cd5d3d6e53597f6b91dc2d283 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 14 Nov 2024 14:11:36 +0200 Subject: [PATCH 029/340] Remove unsetting index length for strings --- app/controllers/api/databases.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 0114fd343c..33a47dfff1 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2587,7 +2587,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeStatus = $oldAttributes[$attributeIndex]['status']; $attributeType = $oldAttributes[$attributeIndex]['type']; - $attributeSize = $oldAttributes[$attributeIndex]['size']; $attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false; if ($attributeType === Database::VAR_RELATIONSHIP) { @@ -2601,10 +2600,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $lengths[$i] = null; - if ($attributeType === Database::VAR_STRING) { - $lengths[$i] = $attributeSize; // set attribute size as index length only for strings - } - if ($attributeArray === true) { $lengths[$i] = Database::ARRAY_INDEX_LENGTH; $orders[$i] = null; From d8799e5a9c67a2d91e9bd2846e251690239f2bea Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 14 Nov 2024 14:13:28 +0200 Subject: [PATCH 030/340] Remove comment --- app/controllers/api/databases.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 81aee28ad7..13bb8c53b2 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2608,7 +2608,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); } - // todo: Think of a better solution $lengths[$i] = null; if ($attributeArray === true) { From abf97e391e92121a7965f2db1ffdc329f51f8853 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 14 Nov 2024 14:19:33 +0200 Subject: [PATCH 031/340] formatting --- app/controllers/api/databases.php | 1 - composer.lock | 62 +++++++++++++++---------------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 13bb8c53b2..4dfaf0cd5c 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -20,7 +20,6 @@ use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; diff --git a/composer.lock b/composer.lock index 508de82034..26da13625d 100644 --- a/composer.lock +++ b/composer.lock @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.1.7", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0" + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", - "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", "shasum": "" }, "require": { @@ -2527,7 +2527,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.7" + "source": "https://github.com/symfony/http-client/tree/v7.1.8" }, "funding": [ { @@ -2543,7 +2543,7 @@ "type": "tidelift" } ], - "time": "2024-11-05T16:45:54+00:00" + "time": "2024-11-13T13:40:27+00:00" }, { "name": "symfony/http-client-contracts", @@ -4806,16 +4806,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.24", + "version": "0.39.25", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8" + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/412451c87f6ef17e24e9a5cf41721043d74c60c8", - "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5b5323636a8d75a1c4faaae9728098dd6a6a47d1", + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1", "shasum": "" }, "require": { @@ -4823,7 +4823,7 @@ "ext-json": "*", "ext-mbstring": "*", "matthiasmullie/minify": "1.3.*", - "php": ">=8.0", + "php": ">=8.3", "twig/twig": "3.14.*" }, "require-dev": { @@ -4851,9 +4851,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.24" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.25" }, - "time": "2024-10-09T19:13:27+00:00" + "time": "2024-11-08T10:16:34+00:00" }, { "name": "doctrine/annotations", @@ -7576,16 +7576,16 @@ }, { "name": "symfony/console", - "version": "v7.1.7", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a" + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3284aafcac338b6e86fd955ee4d794cbe434151a", - "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a", + "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", "shasum": "" }, "require": { @@ -7649,7 +7649,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.7" + "source": "https://github.com/symfony/console/tree/v7.1.8" }, "funding": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-05T15:34:55+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/filesystem", @@ -8180,16 +8180,16 @@ }, { "name": "symfony/process", - "version": "v7.1.7", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "9b8a40b7289767aa7117e957573c2a535efe6585" + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/9b8a40b7289767aa7117e957573c2a535efe6585", - "reference": "9b8a40b7289767aa7117e957573c2a535efe6585", + "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", "shasum": "" }, "require": { @@ -8221,7 +8221,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.7" + "source": "https://github.com/symfony/process/tree/v7.1.8" }, "funding": [ { @@ -8237,20 +8237,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T09:25:12+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/string", - "version": "v7.1.6", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", + "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", "shasum": "" }, "require": { @@ -8308,7 +8308,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.6" + "source": "https://github.com/symfony/string/tree/v7.1.8" }, "funding": [ { @@ -8324,7 +8324,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-13T13:31:21+00:00" }, { "name": "textalk/websocket", From 7e7a4658cdaf885875bdacfb9a1c4476f030a0e4 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 14 Nov 2024 14:20:28 +0200 Subject: [PATCH 032/340] revert lock --- composer.lock | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/composer.lock b/composer.lock index 26da13625d..508de82034 100644 --- a/composer.lock +++ b/composer.lock @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.1.8", + "version": "v7.1.7", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" + "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "url": "https://api.github.com/repos/symfony/http-client/zipball/90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", + "reference": "90ab2a4992dcf5d1f19a9b8737eba36a7c305fd0", "shasum": "" }, "require": { @@ -2527,7 +2527,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.8" + "source": "https://github.com/symfony/http-client/tree/v7.1.7" }, "funding": [ { @@ -2543,7 +2543,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:40:27+00:00" + "time": "2024-11-05T16:45:54+00:00" }, { "name": "symfony/http-client-contracts", @@ -4806,16 +4806,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.25", + "version": "0.39.24", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" + "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8" }, "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/412451c87f6ef17e24e9a5cf41721043d74c60c8", + "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8", "shasum": "" }, "require": { @@ -4823,7 +4823,7 @@ "ext-json": "*", "ext-mbstring": "*", "matthiasmullie/minify": "1.3.*", - "php": ">=8.3", + "php": ">=8.0", "twig/twig": "3.14.*" }, "require-dev": { @@ -4851,9 +4851,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.24" }, - "time": "2024-11-08T10:16:34+00:00" + "time": "2024-10-09T19:13:27+00:00" }, { "name": "doctrine/annotations", @@ -7576,16 +7576,16 @@ }, { "name": "symfony/console", - "version": "v7.1.8", + "version": "v7.1.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" + "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "url": "https://api.github.com/repos/symfony/console/zipball/3284aafcac338b6e86fd955ee4d794cbe434151a", + "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a", "shasum": "" }, "require": { @@ -7649,7 +7649,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.8" + "source": "https://github.com/symfony/console/tree/v7.1.7" }, "funding": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-05T15:34:55+00:00" }, { "name": "symfony/filesystem", @@ -8180,16 +8180,16 @@ }, { "name": "symfony/process", - "version": "v7.1.8", + "version": "v7.1.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" + "reference": "9b8a40b7289767aa7117e957573c2a535efe6585" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", + "url": "https://api.github.com/repos/symfony/process/zipball/9b8a40b7289767aa7117e957573c2a535efe6585", + "reference": "9b8a40b7289767aa7117e957573c2a535efe6585", "shasum": "" }, "require": { @@ -8221,7 +8221,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.8" + "source": "https://github.com/symfony/process/tree/v7.1.7" }, "funding": [ { @@ -8237,20 +8237,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T09:25:12+00:00" }, { "name": "symfony/string", - "version": "v7.1.8", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", + "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", "shasum": "" }, "require": { @@ -8308,7 +8308,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.8" + "source": "https://github.com/symfony/string/tree/v7.1.6" }, "funding": [ { @@ -8324,7 +8324,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:21+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "textalk/websocket", From 8e021158286cd04b64b391afe86975e23368a52c Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 15 Nov 2024 13:27:46 +0100 Subject: [PATCH 033/340] ci: console sdk previews (#8990) --- .github/workflows/sdk-preview.yml | 33 + .gitignore | 1 + app/config/specs/open-api3-latest-client.json | 28 +- .../specs/open-api3-latest-console.json | 104 +- app/config/specs/open-api3-latest-server.json | 48 +- app/config/specs/swagger2-latest-client.json | 138 +- app/config/specs/swagger2-latest-console.json | 214 +- app/config/specs/swagger2-latest-server.json | 158 +- composer.json | 2 +- composer.lock | 2364 ++++++++++++++--- src/Appwrite/Platform/Tasks/SDKs.php | 33 +- .../Specification/Format/OpenAPI3.php | 1 + .../Specification/Format/Swagger2.php | 1 + 13 files changed, 2355 insertions(+), 770 deletions(-) create mode 100644 .github/workflows/sdk-preview.yml diff --git a/.github/workflows/sdk-preview.yml b/.github/workflows/sdk-preview.yml new file mode 100644 index 0000000000..92b4f454cb --- /dev/null +++ b/.github/workflows/sdk-preview.yml @@ -0,0 +1,33 @@ +name: "Console SDK Preview" + +on: + pull_request: + paths: + - 'app/config/specs/*-latest-console.json' + + +jobs: + setup: + name: Setup & Build Console SDK + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Load and Start Appwrite + run: | + docker compose build + docker compose up -d + docker compose exec appwrite sdks --platform=console --sdk=web --version=latest --git=no + sudo chown -R $USER:$USER ./app/sdks/console-web + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Build and Publish SDK + working-directory: ./app/sdks/console-web + run: | + npm install + npm run build + npx pkg-pr-new publish --comment=update diff --git a/.gitignore b/.gitignore index 5ae03e2a56..0c19fd215e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ dev/yasd_init.php .phpunit.result.cache Makefile appwrite.json +/.zed/ \ No newline at end of file diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 8a9967090d..50e3426e0b 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -239,7 +239,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "tags": [ "account" @@ -556,7 +556,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "tags": [ "account" @@ -624,7 +624,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "tags": [ "account" @@ -711,7 +711,7 @@ } }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "tags": [ "account" @@ -774,7 +774,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "tags": [ "account" @@ -850,7 +850,7 @@ } }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "tags": [ "account" @@ -928,7 +928,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "tags": [ "account" @@ -981,7 +981,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "tags": [ "account" @@ -1032,7 +1032,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "tags": [ "account" @@ -1083,7 +1083,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "tags": [ "account" @@ -5082,9 +5082,9 @@ "type": "object", "properties": { "body": { - "type": "string", + "type": "object", "description": "HTTP body of execution. Default value is empty string.", - "x-example": null + "x-example": "{}" }, "async": { "type": "boolean", @@ -5368,7 +5368,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "tags": [ "locale" @@ -6268,7 +6268,7 @@ } }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "tags": [ "storage" diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 07749889d8..e5f1ad6549 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -278,7 +278,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "tags": [ "account" @@ -591,7 +591,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "tags": [ "account" @@ -658,7 +658,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "tags": [ "account" @@ -744,7 +744,7 @@ } }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "tags": [ "account" @@ -806,7 +806,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "tags": [ "account" @@ -882,7 +882,7 @@ } }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "tags": [ "account" @@ -959,7 +959,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "tags": [ "account" @@ -1011,7 +1011,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "tags": [ "account" @@ -1061,7 +1061,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "tags": [ "account" @@ -1111,7 +1111,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "tags": [ "account" @@ -4452,7 +4452,7 @@ }, "\/console\/assistant": { "post": { - "summary": "Ask Query", + "summary": "Ask query", "operationId": "assistantChat", "tags": [ "assistant" @@ -11052,9 +11052,9 @@ "type": "object", "properties": { "body": { - "type": "string", + "type": "object", "description": "HTTP body of execution. Default value is empty string.", - "x-example": null + "x-example": "{}" }, "async": { "type": "boolean", @@ -13257,7 +13257,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "tags": [ "locale" @@ -18060,7 +18060,7 @@ }, "\/migrations": { "get": { - "summary": "List Migrations", + "summary": "List migrations", "operationId": "migrationsList", "tags": [ "migrations" @@ -18136,7 +18136,7 @@ }, "\/migrations\/appwrite": { "post": { - "summary": "Migrate Appwrite Data", + "summary": "Migrate Appwrite data", "operationId": "migrationsCreateAppwriteMigration", "tags": [ "migrations" @@ -18226,7 +18226,7 @@ }, "\/migrations\/appwrite\/report": { "get": { - "summary": "Generate a report on Appwrite Data", + "summary": "Generate a report on Appwrite data", "operationId": "migrationsGetAppwriteReport", "tags": [ "migrations" @@ -18321,7 +18321,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase Data (Service Account)", + "summary": "Migrate Firebase data (Service Account)", "operationId": "migrationsCreateFirebaseMigration", "tags": [ "migrations" @@ -18399,7 +18399,7 @@ }, "\/migrations\/firebase\/deauthorize": { "get": { - "summary": "Revoke Appwrite's authorization to access Firebase Projects", + "summary": "Revoke Appwrite's authorization to access Firebase projects", "operationId": "migrationsDeleteFirebaseAuth", "tags": [ "migrations" @@ -18442,7 +18442,7 @@ }, "\/migrations\/firebase\/oauth": { "post": { - "summary": "Migrate Firebase Data (OAuth)", + "summary": "Migrate Firebase data (OAuth)", "operationId": "migrationsCreateFirebaseOAuthMigration", "tags": [ "migrations" @@ -18520,7 +18520,7 @@ }, "\/migrations\/firebase\/projects": { "get": { - "summary": "List Firebase Projects", + "summary": "List Firebase projects", "operationId": "migrationsListFirebaseProjects", "tags": [ "migrations" @@ -18570,7 +18570,7 @@ }, "\/migrations\/firebase\/report": { "get": { - "summary": "Generate a report on Firebase Data", + "summary": "Generate a report on Firebase data", "operationId": "migrationsGetFirebaseReport", "tags": [ "migrations" @@ -18644,7 +18644,7 @@ }, "\/migrations\/firebase\/report\/oauth": { "get": { - "summary": "Generate a report on Firebase Data using OAuth", + "summary": "Generate a report on Firebase data using OAuth", "operationId": "migrationsGetFirebaseReportOAuth", "tags": [ "migrations" @@ -18718,7 +18718,7 @@ }, "\/migrations\/nhost": { "post": { - "summary": "Migrate NHost Data", + "summary": "Migrate NHost data", "operationId": "migrationsCreateNHostMigration", "tags": [ "migrations" @@ -18966,7 +18966,7 @@ }, "\/migrations\/supabase": { "post": { - "summary": "Migrate Supabase Data", + "summary": "Migrate Supabase data", "operationId": "migrationsCreateSupabaseMigration", "tags": [ "migrations" @@ -19199,7 +19199,7 @@ }, "\/migrations\/{migrationId}": { "get": { - "summary": "Get Migration", + "summary": "Get migration", "operationId": "migrationsGet", "tags": [ "migrations" @@ -19259,7 +19259,7 @@ ] }, "patch": { - "summary": "Retry Migration", + "summary": "Retry migration", "operationId": "migrationsRetry", "tags": [ "migrations" @@ -19319,7 +19319,7 @@ ] }, "delete": { - "summary": "Delete Migration", + "summary": "Delete migration", "operationId": "migrationsDelete", "tags": [ "migrations" @@ -19464,7 +19464,7 @@ }, "\/project\/variables": { "get": { - "summary": "List Variables", + "summary": "List variables", "operationId": "projectListVariables", "tags": [ "project" @@ -19512,7 +19512,7 @@ ] }, "post": { - "summary": "Create Variable", + "summary": "Create variable", "operationId": "projectCreateVariable", "tags": [ "project" @@ -19587,7 +19587,7 @@ }, "\/project\/variables\/{variableId}": { "get": { - "summary": "Get Variable", + "summary": "Get variable", "operationId": "projectGetVariable", "tags": [ "project" @@ -19647,7 +19647,7 @@ ] }, "put": { - "summary": "Update Variable", + "summary": "Update variable", "operationId": "projectUpdateVariable", "tags": [ "project" @@ -19731,7 +19731,7 @@ } }, "delete": { - "summary": "Delete Variable", + "summary": "Delete variable", "operationId": "projectDeleteVariable", "tags": [ "project" @@ -24640,7 +24640,7 @@ }, "\/proxy\/rules": { "get": { - "summary": "List Rules", + "summary": "List rules", "operationId": "proxyListRules", "tags": [ "proxy" @@ -24714,7 +24714,7 @@ ] }, "post": { - "summary": "Create Rule", + "summary": "Create rule", "operationId": "proxyCreateRule", "tags": [ "proxy" @@ -24800,7 +24800,7 @@ }, "\/proxy\/rules\/{ruleId}": { "get": { - "summary": "Get Rule", + "summary": "Get rule", "operationId": "proxyGetRule", "tags": [ "proxy" @@ -24860,7 +24860,7 @@ ] }, "delete": { - "summary": "Delete Rule", + "summary": "Delete rule", "operationId": "proxyDeleteRule", "tags": [ "proxy" @@ -24915,7 +24915,7 @@ }, "\/proxy\/rules\/{ruleId}\/verification": { "patch": { - "summary": "Update Rule Verification Status", + "summary": "Update rule verification status", "operationId": "proxyUpdateRuleVerification", "tags": [ "proxy" @@ -25791,7 +25791,7 @@ } }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "tags": [ "storage" @@ -27842,7 +27842,7 @@ }, "\/users\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "usersListIdentities", "tags": [ "users" @@ -29141,7 +29141,7 @@ }, "\/users\/{userId}\/mfa\/authenticators\/{type}": { "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "usersDeleteMfaAuthenticator", "tags": [ "users" @@ -29219,7 +29219,7 @@ }, "\/users\/{userId}\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "usersListMfaFactors", "tags": [ "users" @@ -29282,7 +29282,7 @@ }, "\/users\/{userId}\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "usersGetMfaRecoveryCodes", "tags": [ "users" @@ -29343,7 +29343,7 @@ ] }, "put": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "usersUpdateMfaRecoveryCodes", "tags": [ "users" @@ -29404,7 +29404,7 @@ ] }, "patch": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "usersCreateMfaRecoveryCodes", "tags": [ "users" @@ -30182,7 +30182,7 @@ }, "\/users\/{userId}\/targets": { "get": { - "summary": "List User Targets", + "summary": "List user targets", "operationId": "usersListTargets", "tags": [ "users" @@ -30257,7 +30257,7 @@ ] }, "post": { - "summary": "Create User Target", + "summary": "Create user target", "operationId": "usersCreateTarget", "tags": [ "users" @@ -30369,7 +30369,7 @@ }, "\/users\/{userId}\/targets\/{targetId}": { "get": { - "summary": "Get User Target", + "summary": "Get user target", "operationId": "usersGetTarget", "tags": [ "users" @@ -30441,7 +30441,7 @@ ] }, "patch": { - "summary": "Update User target", + "summary": "Update user target", "operationId": "usersUpdateTarget", "tags": [ "users" @@ -30854,7 +30854,7 @@ }, "\/vcs\/github\/installations\/{installationId}\/providerRepositories": { "get": { - "summary": "List Repositories", + "summary": "List repositories", "operationId": "vcsListRepositories", "tags": [ "vcs" @@ -31084,7 +31084,7 @@ }, "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/branches": { "get": { - "summary": "List Repository Branches", + "summary": "List repository branches", "operationId": "vcsListRepositoryBranches", "tags": [ "vcs" @@ -31547,7 +31547,7 @@ ] }, "delete": { - "summary": "Delete Installation", + "summary": "Delete installation", "operationId": "vcsDeleteInstallation", "tags": [ "vcs" diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index ef41688ca8..6bb83643ed 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -241,7 +241,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "tags": [ "account" @@ -562,7 +562,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "tags": [ "account" @@ -631,7 +631,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "tags": [ "account" @@ -719,7 +719,7 @@ } }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "tags": [ "account" @@ -783,7 +783,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "tags": [ "account" @@ -859,7 +859,7 @@ } }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "tags": [ "account" @@ -938,7 +938,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "tags": [ "account" @@ -992,7 +992,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "tags": [ "account" @@ -1044,7 +1044,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "tags": [ "account" @@ -1096,7 +1096,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "tags": [ "account" @@ -9939,9 +9939,9 @@ "type": "object", "properties": { "body": { - "type": "string", + "type": "object", "description": "HTTP body of execution. Default value is empty string.", - "x-example": null + "x-example": "{}" }, "async": { "type": "boolean", @@ -12097,7 +12097,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "tags": [ "locale" @@ -17789,7 +17789,7 @@ } }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "tags": [ "storage" @@ -19645,7 +19645,7 @@ }, "\/users\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "usersListIdentities", "tags": [ "users" @@ -20885,7 +20885,7 @@ }, "\/users\/{userId}\/mfa\/authenticators\/{type}": { "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "usersDeleteMfaAuthenticator", "tags": [ "users" @@ -20964,7 +20964,7 @@ }, "\/users\/{userId}\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "usersListMfaFactors", "tags": [ "users" @@ -21028,7 +21028,7 @@ }, "\/users\/{userId}\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "usersGetMfaRecoveryCodes", "tags": [ "users" @@ -21090,7 +21090,7 @@ ] }, "put": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "usersUpdateMfaRecoveryCodes", "tags": [ "users" @@ -21152,7 +21152,7 @@ ] }, "patch": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "usersCreateMfaRecoveryCodes", "tags": [ "users" @@ -21941,7 +21941,7 @@ }, "\/users\/{userId}\/targets": { "get": { - "summary": "List User Targets", + "summary": "List user targets", "operationId": "usersListTargets", "tags": [ "users" @@ -22017,7 +22017,7 @@ ] }, "post": { - "summary": "Create User Target", + "summary": "Create user target", "operationId": "usersCreateTarget", "tags": [ "users" @@ -22130,7 +22130,7 @@ }, "\/users\/{userId}\/targets\/{targetId}": { "get": { - "summary": "Get User Target", + "summary": "Get user target", "operationId": "usersGetTarget", "tags": [ "users" @@ -22203,7 +22203,7 @@ ] }, "patch": { - "summary": "Update User target", + "summary": "Update user target", "operationId": "usersUpdateTarget", "tags": [ "users" diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index ce9ea857bb..a35e496d66 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -293,7 +293,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "consumes": [ "application\/json" @@ -619,7 +619,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "consumes": [ "application\/json" @@ -687,7 +687,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "consumes": [ "application\/json" @@ -773,7 +773,7 @@ ] }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "consumes": [ "application\/json" @@ -838,7 +838,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "consumes": [ "application\/json" @@ -917,7 +917,7 @@ ] }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "consumes": [ "application\/json" @@ -994,7 +994,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "consumes": [ "application\/json" @@ -1049,7 +1049,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1102,7 +1102,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1155,7 +1155,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -5167,7 +5167,7 @@ "summary": "Create execution", "operationId": "functionsCreateExecution", "consumes": [ - "multipart\/form-data" + "application\/json" ], "produces": [ "multipart\/form-data" @@ -5226,65 +5226,59 @@ "in": "path" }, { - "name": "body", - "description": "HTTP body of execution. Default value is empty string.", - "required": false, - "type": "payload", - "default": "", - "in": "formData" - }, - { - "name": "async", - "description": "Execute code in the background. Default value is false.", - "required": false, - "type": "boolean", - "x-example": false, - "default": false, - "in": "formData" - }, - { - "name": "path", - "description": "HTTP path of execution. Path can include query params. Default value is \/", - "required": false, - "type": "string", - "x-example": "", - "default": "\/", - "in": "formData" - }, - { - "name": "method", - "description": "HTTP method of execution. Default value is GET.", - "required": false, - "type": "string", - "x-example": "GET", - "enum": [ - "GET", - "POST", - "PUT", - "PATCH", - "DELETE", - "OPTIONS" - ], - "x-enum-name": "ExecutionMethod", - "x-enum-keys": [], - "default": "POST", - "in": "formData" - }, - { - "name": "headers", - "description": "HTTP headers of execution. Defaults to empty.", - "required": false, - "type": "object", - "default": [], - "x-example": "{}", - "in": "formData" - }, - { - "name": "scheduledAt", - "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", - "required": false, - "type": "string", - "in": "formData" + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "object", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "{}" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } } ] } @@ -5573,7 +5567,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "consumes": [ "application\/json" @@ -6476,7 +6470,7 @@ ] }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 51935a5e01..963f55eae1 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -348,7 +348,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "consumes": [ "application\/json" @@ -670,7 +670,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "consumes": [ "application\/json" @@ -737,7 +737,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "consumes": [ "application\/json" @@ -822,7 +822,7 @@ ] }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "consumes": [ "application\/json" @@ -886,7 +886,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "consumes": [ "application\/json" @@ -965,7 +965,7 @@ ] }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "consumes": [ "application\/json" @@ -1041,7 +1041,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "consumes": [ "application\/json" @@ -1095,7 +1095,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1147,7 +1147,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1199,7 +1199,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -4637,7 +4637,7 @@ }, "\/console\/assistant": { "post": { - "summary": "Ask Query", + "summary": "Ask query", "operationId": "assistantChat", "consumes": [ "application\/json" @@ -11131,7 +11131,7 @@ "summary": "Create execution", "operationId": "functionsCreateExecution", "consumes": [ - "multipart\/form-data" + "application\/json" ], "produces": [ "multipart\/form-data" @@ -11190,65 +11190,59 @@ "in": "path" }, { - "name": "body", - "description": "HTTP body of execution. Default value is empty string.", - "required": false, - "type": "payload", - "default": "", - "in": "formData" - }, - { - "name": "async", - "description": "Execute code in the background. Default value is false.", - "required": false, - "type": "boolean", - "x-example": false, - "default": false, - "in": "formData" - }, - { - "name": "path", - "description": "HTTP path of execution. Path can include query params. Default value is \/", - "required": false, - "type": "string", - "x-example": "", - "default": "\/", - "in": "formData" - }, - { - "name": "method", - "description": "HTTP method of execution. Default value is GET.", - "required": false, - "type": "string", - "x-example": "GET", - "enum": [ - "GET", - "POST", - "PUT", - "PATCH", - "DELETE", - "OPTIONS" - ], - "x-enum-name": "ExecutionMethod", - "x-enum-keys": [], - "default": "POST", - "in": "formData" - }, - { - "name": "headers", - "description": "HTTP headers of execution. Defaults to empty.", - "required": false, - "type": "object", - "default": [], - "x-example": "{}", - "in": "formData" - }, - { - "name": "scheduledAt", - "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", - "required": false, - "type": "string", - "in": "formData" + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "object", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "{}" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } } ] } @@ -13464,7 +13458,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "consumes": [ "application\/json" @@ -18494,7 +18488,7 @@ }, "\/migrations": { "get": { - "summary": "List Migrations", + "summary": "List migrations", "operationId": "migrationsList", "consumes": [ "application\/json" @@ -18569,7 +18563,7 @@ }, "\/migrations\/appwrite": { "post": { - "summary": "Migrate Appwrite Data", + "summary": "Migrate Appwrite data", "operationId": "migrationsCreateAppwriteMigration", "consumes": [ "application\/json" @@ -18665,7 +18659,7 @@ }, "\/migrations\/appwrite\/report": { "get": { - "summary": "Generate a report on Appwrite Data", + "summary": "Generate a report on Appwrite data", "operationId": "migrationsGetAppwriteReport", "consumes": [ "application\/json" @@ -18755,7 +18749,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase Data (Service Account)", + "summary": "Migrate Firebase data (Service Account)", "operationId": "migrationsCreateFirebaseMigration", "consumes": [ "application\/json" @@ -18837,7 +18831,7 @@ }, "\/migrations\/firebase\/deauthorize": { "get": { - "summary": "Revoke Appwrite's authorization to access Firebase Projects", + "summary": "Revoke Appwrite's authorization to access Firebase projects", "operationId": "migrationsDeleteFirebaseAuth", "consumes": [ "application\/json" @@ -18889,7 +18883,7 @@ }, "\/migrations\/firebase\/oauth": { "post": { - "summary": "Migrate Firebase Data (OAuth)", + "summary": "Migrate Firebase data (OAuth)", "operationId": "migrationsCreateFirebaseOAuthMigration", "consumes": [ "application\/json" @@ -18971,7 +18965,7 @@ }, "\/migrations\/firebase\/projects": { "get": { - "summary": "List Firebase Projects", + "summary": "List Firebase projects", "operationId": "migrationsListFirebaseProjects", "consumes": [ "application\/json" @@ -19023,7 +19017,7 @@ }, "\/migrations\/firebase\/report": { "get": { - "summary": "Generate a report on Firebase Data", + "summary": "Generate a report on Firebase data", "operationId": "migrationsGetFirebaseReport", "consumes": [ "application\/json" @@ -19096,7 +19090,7 @@ }, "\/migrations\/firebase\/report\/oauth": { "get": { - "summary": "Generate a report on Firebase Data using OAuth", + "summary": "Generate a report on Firebase data using OAuth", "operationId": "migrationsGetFirebaseReportOAuth", "consumes": [ "application\/json" @@ -19169,7 +19163,7 @@ }, "\/migrations\/nhost": { "post": { - "summary": "Migrate NHost Data", + "summary": "Migrate NHost data", "operationId": "migrationsCreateNHostMigration", "consumes": [ "application\/json" @@ -19414,7 +19408,7 @@ }, "\/migrations\/supabase": { "post": { - "summary": "Migrate Supabase Data", + "summary": "Migrate Supabase data", "operationId": "migrationsCreateSupabaseMigration", "consumes": [ "application\/json" @@ -19645,7 +19639,7 @@ }, "\/migrations\/{migrationId}": { "get": { - "summary": "Get Migration", + "summary": "Get migration", "operationId": "migrationsGet", "consumes": [ "application\/json" @@ -19705,7 +19699,7 @@ ] }, "patch": { - "summary": "Retry Migration", + "summary": "Retry migration", "operationId": "migrationsRetry", "consumes": [ "application\/json" @@ -19765,7 +19759,7 @@ ] }, "delete": { - "summary": "Delete Migration", + "summary": "Delete migration", "operationId": "migrationsDelete", "consumes": [ "application\/json" @@ -19908,7 +19902,7 @@ }, "\/project\/variables": { "get": { - "summary": "List Variables", + "summary": "List variables", "operationId": "projectListVariables", "consumes": [ "application\/json" @@ -19958,7 +19952,7 @@ ] }, "post": { - "summary": "Create Variable", + "summary": "Create variable", "operationId": "projectCreateVariable", "consumes": [ "application\/json" @@ -20037,7 +20031,7 @@ }, "\/project\/variables\/{variableId}": { "get": { - "summary": "Get Variable", + "summary": "Get variable", "operationId": "projectGetVariable", "consumes": [ "application\/json" @@ -20097,7 +20091,7 @@ ] }, "put": { - "summary": "Update Variable", + "summary": "Update variable", "operationId": "projectUpdateVariable", "consumes": [ "application\/json" @@ -20181,7 +20175,7 @@ ] }, "delete": { - "summary": "Delete Variable", + "summary": "Delete variable", "operationId": "projectDeleteVariable", "consumes": [ "application\/json" @@ -25101,7 +25095,7 @@ }, "\/proxy\/rules": { "get": { - "summary": "List Rules", + "summary": "List rules", "operationId": "proxyListRules", "consumes": [ "application\/json" @@ -25174,7 +25168,7 @@ ] }, "post": { - "summary": "Create Rule", + "summary": "Create rule", "operationId": "proxyCreateRule", "consumes": [ "application\/json" @@ -25265,7 +25259,7 @@ }, "\/proxy\/rules\/{ruleId}": { "get": { - "summary": "Get Rule", + "summary": "Get rule", "operationId": "proxyGetRule", "consumes": [ "application\/json" @@ -25325,7 +25319,7 @@ ] }, "delete": { - "summary": "Delete Rule", + "summary": "Delete rule", "operationId": "proxyDeleteRule", "consumes": [ "application\/json" @@ -25382,7 +25376,7 @@ }, "\/proxy\/rules\/{ruleId}\/verification": { "patch": { - "summary": "Update Rule Verification Status", + "summary": "Update rule verification status", "operationId": "proxyUpdateRuleVerification", "consumes": [ "application\/json" @@ -26265,7 +26259,7 @@ ] }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "consumes": [ "application\/json" @@ -28324,7 +28318,7 @@ }, "\/users\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "usersListIdentities", "consumes": [ "application\/json" @@ -29661,7 +29655,7 @@ }, "\/users\/{userId}\/mfa\/authenticators\/{type}": { "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "usersDeleteMfaAuthenticator", "consumes": [ "application\/json" @@ -29737,7 +29731,7 @@ }, "\/users\/{userId}\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "usersListMfaFactors", "consumes": [ "application\/json" @@ -29800,7 +29794,7 @@ }, "\/users\/{userId}\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "usersGetMfaRecoveryCodes", "consumes": [ "application\/json" @@ -29861,7 +29855,7 @@ ] }, "put": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "usersUpdateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -29922,7 +29916,7 @@ ] }, "patch": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "usersCreateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -30697,7 +30691,7 @@ }, "\/users\/{userId}\/targets": { "get": { - "summary": "List User Targets", + "summary": "List user targets", "operationId": "usersListTargets", "consumes": [ "application\/json" @@ -30771,7 +30765,7 @@ ] }, "post": { - "summary": "Create User Target", + "summary": "Create user target", "operationId": "usersCreateTarget", "consumes": [ "application\/json" @@ -30886,7 +30880,7 @@ }, "\/users\/{userId}\/targets\/{targetId}": { "get": { - "summary": "Get User Target", + "summary": "Get user target", "operationId": "usersGetTarget", "consumes": [ "application\/json" @@ -30956,7 +30950,7 @@ ] }, "patch": { - "summary": "Update User target", + "summary": "Update user target", "operationId": "usersUpdateTarget", "consumes": [ "application\/json" @@ -31368,7 +31362,7 @@ }, "\/vcs\/github\/installations\/{installationId}\/providerRepositories": { "get": { - "summary": "List Repositories", + "summary": "List repositories", "operationId": "vcsListRepositories", "consumes": [ "application\/json" @@ -31594,7 +31588,7 @@ }, "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/branches": { "get": { - "summary": "List Repository Branches", + "summary": "List repository branches", "operationId": "vcsListRepositoryBranches", "consumes": [ "application\/json" @@ -32046,7 +32040,7 @@ ] }, "delete": { - "summary": "Delete Installation", + "summary": "Delete installation", "operationId": "vcsDeleteInstallation", "consumes": [ "application\/json" diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index af6274226f..705dc5a54b 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -310,7 +310,7 @@ }, "\/account\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "accountListIdentities", "consumes": [ "application\/json" @@ -640,7 +640,7 @@ }, "\/account\/mfa\/authenticators\/{type}": { "post": { - "summary": "Create Authenticator", + "summary": "Create authenticator", "operationId": "accountCreateMfaAuthenticator", "consumes": [ "application\/json" @@ -709,7 +709,7 @@ ] }, "put": { - "summary": "Verify Authenticator", + "summary": "Verify authenticator", "operationId": "accountUpdateMfaAuthenticator", "consumes": [ "application\/json" @@ -796,7 +796,7 @@ ] }, "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "accountDeleteMfaAuthenticator", "consumes": [ "application\/json" @@ -862,7 +862,7 @@ }, "\/account\/mfa\/challenge": { "post": { - "summary": "Create MFA Challenge", + "summary": "Create MFA challenge", "operationId": "accountCreateMfaChallenge", "consumes": [ "application\/json" @@ -941,7 +941,7 @@ ] }, "put": { - "summary": "Create MFA Challenge (confirmation)", + "summary": "Create MFA challenge (confirmation)", "operationId": "accountUpdateMfaChallenge", "consumes": [ "application\/json" @@ -1019,7 +1019,7 @@ }, "\/account\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "accountListMfaFactors", "consumes": [ "application\/json" @@ -1075,7 +1075,7 @@ }, "\/account\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "accountGetMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1129,7 +1129,7 @@ ] }, "post": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "accountCreateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -1183,7 +1183,7 @@ ] }, "patch": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "accountUpdateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -10022,7 +10022,7 @@ "summary": "Create execution", "operationId": "functionsCreateExecution", "consumes": [ - "multipart\/form-data" + "application\/json" ], "produces": [ "multipart\/form-data" @@ -10083,65 +10083,59 @@ "in": "path" }, { - "name": "body", - "description": "HTTP body of execution. Default value is empty string.", - "required": false, - "type": "payload", - "default": "", - "in": "formData" - }, - { - "name": "async", - "description": "Execute code in the background. Default value is false.", - "required": false, - "type": "boolean", - "x-example": false, - "default": false, - "in": "formData" - }, - { - "name": "path", - "description": "HTTP path of execution. Path can include query params. Default value is \/", - "required": false, - "type": "string", - "x-example": "", - "default": "\/", - "in": "formData" - }, - { - "name": "method", - "description": "HTTP method of execution. Default value is GET.", - "required": false, - "type": "string", - "x-example": "GET", - "enum": [ - "GET", - "POST", - "PUT", - "PATCH", - "DELETE", - "OPTIONS" - ], - "x-enum-name": "ExecutionMethod", - "x-enum-keys": [], - "default": "POST", - "in": "formData" - }, - { - "name": "headers", - "description": "HTTP headers of execution. Defaults to empty.", - "required": false, - "type": "object", - "default": [], - "x-example": "{}", - "in": "formData" - }, - { - "name": "scheduledAt", - "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", - "required": false, - "type": "string", - "in": "formData" + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "object", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "{}" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } } ] } @@ -12312,7 +12306,7 @@ }, "\/locale\/codes": { "get": { - "summary": "List Locale Codes", + "summary": "List locale codes", "operationId": "localeListCodes", "consumes": [ "application\/json" @@ -18238,7 +18232,7 @@ ] }, "delete": { - "summary": "Delete File", + "summary": "Delete file", "operationId": "storageDeleteFile", "consumes": [ "application\/json" @@ -20105,7 +20099,7 @@ }, "\/users\/identities": { "get": { - "summary": "List Identities", + "summary": "List identities", "operationId": "usersListIdentities", "consumes": [ "application\/json" @@ -21383,7 +21377,7 @@ }, "\/users\/{userId}\/mfa\/authenticators\/{type}": { "delete": { - "summary": "Delete Authenticator", + "summary": "Delete authenticator", "operationId": "usersDeleteMfaAuthenticator", "consumes": [ "application\/json" @@ -21460,7 +21454,7 @@ }, "\/users\/{userId}\/mfa\/factors": { "get": { - "summary": "List Factors", + "summary": "List factors", "operationId": "usersListMfaFactors", "consumes": [ "application\/json" @@ -21524,7 +21518,7 @@ }, "\/users\/{userId}\/mfa\/recovery-codes": { "get": { - "summary": "Get MFA Recovery Codes", + "summary": "Get MFA recovery codes", "operationId": "usersGetMfaRecoveryCodes", "consumes": [ "application\/json" @@ -21586,7 +21580,7 @@ ] }, "put": { - "summary": "Regenerate MFA Recovery Codes", + "summary": "Regenerate MFA recovery codes", "operationId": "usersUpdateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -21648,7 +21642,7 @@ ] }, "patch": { - "summary": "Create MFA Recovery Codes", + "summary": "Create MFA recovery codes", "operationId": "usersCreateMfaRecoveryCodes", "consumes": [ "application\/json" @@ -22434,7 +22428,7 @@ }, "\/users\/{userId}\/targets": { "get": { - "summary": "List User Targets", + "summary": "List user targets", "operationId": "usersListTargets", "consumes": [ "application\/json" @@ -22509,7 +22503,7 @@ ] }, "post": { - "summary": "Create User Target", + "summary": "Create user target", "operationId": "usersCreateTarget", "consumes": [ "application\/json" @@ -22625,7 +22619,7 @@ }, "\/users\/{userId}\/targets\/{targetId}": { "get": { - "summary": "Get User Target", + "summary": "Get user target", "operationId": "usersGetTarget", "consumes": [ "application\/json" @@ -22696,7 +22690,7 @@ ] }, "patch": { - "summary": "Update User target", + "summary": "Update user target", "operationId": "usersUpdateTarget", "consumes": [ "application\/json" diff --git a/composer.json b/composer.json index 91ff1eeb92..38ead1fbcd 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.10.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.*", + "utopia-php/database": "0.53.4", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 147800df32..14eb289fa1 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": "b6820da26239716cf14a445697902a03", + "content-hash": "e7fdbd3a7d4375ee8c139cecdaeb2d24", "packages": [ { "name": "adhocore/jwt", @@ -211,16 +211,16 @@ }, { "name": "beberlei/assert", - "version": "v3.3.2", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/beberlei/assert.git", - "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655" + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beberlei/assert/zipball/cb70015c04be1baee6f5f5c953703347c0ac1655", - "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655", + "url": "https://api.github.com/repos/beberlei/assert/zipball/b5fd8eacd8915a1b627b8bfc027803f1939734dd", + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd", "shasum": "" }, "require": { @@ -228,7 +228,7 @@ "ext-json": "*", "ext-mbstring": "*", "ext-simplexml": "*", - "php": "^7.0 || ^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", @@ -272,9 +272,69 @@ ], "support": { "issues": "https://github.com/beberlei/assert/issues", - "source": "https://github.com/beberlei/assert/tree/v3.3.2" + "source": "https://github.com/beberlei/assert/tree/v3.3.3" }, - "time": "2021-12-16T21:41:27+00:00" + "time": "2024-07-15T13:18:35+00:00" + }, + { + "name": "brick/math", + "version": "0.12.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.12.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-11-29T23:19:16+00:00" }, { "name": "chillerlan/php-qrcode", @@ -421,6 +481,87 @@ ], "time": "2024-07-17T01:04:28+00:00" }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.3.2", @@ -565,6 +706,50 @@ }, "time": "2024-05-03T06:31:11+00:00" }, + { + "name": "google/protobuf", + "version": "v4.28.3", + "source": { + "type": "git", + "url": "https://github.com/protocolbuffers/protobuf-php.git", + "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c5c311e0f3d89928251ac5a2f0e3db283612c100", + "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": ">=5.0.0" + }, + "suggest": { + "ext-bcmath": "Need to support JSON deserialization" + }, + "type": "library", + "autoload": { + "psr-4": { + "Google\\Protobuf\\": "src/Google/Protobuf", + "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "proto library for PHP", + "homepage": "https://developers.google.com/protocol-buffers/", + "keywords": [ + "proto" + ], + "support": { + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.28.3" + }, + "time": "2024-10-22T22:27:17+00:00" + }, { "name": "jean85/pretty-package-versions", "version": "2.0.6", @@ -905,6 +1090,553 @@ }, "time": "2019-09-10T13:16:29+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2024-09-09T07:06:30+00:00" + }, + { + "name": "nyholm/psr7-server", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7-server.git", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/4335801d851f554ca43fa6e7d2602141538854dc", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "nyholm/nsa": "^1.1", + "nyholm/psr7": "^1.3", + "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "Helper classes to handle PSR-7 server requests", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7-server/issues", + "source": "https://github.com/Nyholm/psr7-server/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2023-11-08T09:30:43+00:00" + }, + { + "name": "open-telemetry/api", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/api.git", + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", + "shasum": "" + }, + "require": { + "open-telemetry/context": "^1.0", + "php": "^8.1", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/polyfill-php82": "^1.26" + }, + "conflict": { + "open-telemetry/sdk": "<=1.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1.x-dev" + }, + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + } + }, + "autoload": { + "files": [ + "Trace/functions.php" + ], + "psr-4": { + "OpenTelemetry\\API\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "API for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "api", + "apm", + "logging", + "opentelemetry", + "otel", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/context", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/context.git", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "shasum": "" + }, + "require": { + "php": "^8.1", + "symfony/polyfill-php82": "^1.26" + }, + "suggest": { + "ext-ffi": "To allow context switching in Fibers" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "fiber/initialize_fiber_handler.php" + ], + "psr-4": { + "OpenTelemetry\\Context\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Context implementation for OpenTelemetry PHP.", + "keywords": [ + "Context", + "opentelemetry", + "otel" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-08-21T00:29:20+00:00" + }, + { + "name": "open-telemetry/exporter-otlp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/exporter-otlp.git", + "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/9b6de12204f25f8ab9540b46d6e7b5151897ce18", + "reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18", + "shasum": "" + }, + "require": { + "open-telemetry/api": "^1.0", + "open-telemetry/gen-otlp-protobuf": "^1.1", + "open-telemetry/sdk": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "_register.php" + ], + "psr-4": { + "OpenTelemetry\\Contrib\\Otlp\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "OTLP exporter for OpenTelemetry.", + "keywords": [ + "Metrics", + "exporter", + "gRPC", + "http", + "opentelemetry", + "otel", + "otlp", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/gen-otlp-protobuf", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "shasum": "" + }, + "require": { + "google/protobuf": "^3.22 || ^4.0", + "php": "^8.0" + }, + "suggest": { + "ext-protobuf": "For better performance, when dealing with the protobuf format" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opentelemetry\\Proto\\": "Opentelemetry/Proto/", + "GPBMetadata\\Opentelemetry\\": "GPBMetadata/Opentelemetry/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "PHP protobuf files for communication with OpenTelemetry OTLP collectors/servers.", + "keywords": [ + "Metrics", + "apm", + "gRPC", + "logging", + "opentelemetry", + "otel", + "otlp", + "protobuf", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-10-30T11:49:49+00:00" + }, + { + "name": "open-telemetry/sdk", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sdk.git", + "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/fb0ff8d8279a3776bd604791e2531dd0cc147e8b", + "reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nyholm/psr7-server": "^1.1", + "open-telemetry/api": "~1.0 || ~1.1", + "open-telemetry/context": "^1.0", + "open-telemetry/sem-conv": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14", + "psr/http-client": "^1.0", + "psr/http-client-implementation": "^1.0", + "psr/http-factory-implementation": "^1.0", + "psr/http-message": "^1.0.1|^2.0", + "psr/log": "^1.1|^2.0|^3.0", + "ramsey/uuid": "^3.0 || ^4.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php82": "^1.26", + "tbachert/spi": "^1.0.1" + }, + "suggest": { + "ext-gmp": "To support unlimited number of synchronous metric readers", + "ext-mbstring": "To increase performance of string operations", + "open-telemetry/sdk-configuration": "File-based OpenTelemetry SDK configuration" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + }, + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + } + }, + "autoload": { + "files": [ + "Common/Util/functions.php", + "Logs/Exporter/_register.php", + "Metrics/MetricExporter/_register.php", + "Propagation/_register.php", + "Trace/SpanExporter/_register.php", + "Common/Dev/Compatibility/_load.php", + "_autoload.php" + ], + "psr-4": { + "OpenTelemetry\\SDK\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "SDK for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "sdk", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/sem-conv", + "version": "1.27.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sem-conv.git", + "reference": "1dba705fea74bc0718d04be26090e3697e56f4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/1dba705fea74bc0718d04be26090e3697e56f4e6", + "reference": "1dba705fea74bc0718d04be26090e3697e56f4e6", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenTelemetry\\SemConv\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Semantic conventions for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "semantic conventions", + "semconv", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-08-28T09:20:31+00:00" + }, { "name": "paragonie/constant_time_encoding", "version": "v2.7.0", @@ -972,6 +1704,85 @@ }, "time": "2024-05-08T12:18:48+00:00" }, + { + "name": "php-http/discovery", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.20.0" + }, + "time": "2024-10-02T11:20:13+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v6.9.1", @@ -1053,6 +1864,450 @@ ], "time": "2023-11-25T22:23:28+00:00" }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.6", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.6" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2024-04-27T21:32:50+00:00" + }, { "name": "spomky-labs/otphp", "version": "v10.0.3", @@ -1128,6 +2383,245 @@ }, "time": "2022-03-17T08:00:35+00:00" }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/http-client", + "version": "v7.1.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-13T13:40:27+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.31.0", @@ -1288,6 +2782,217 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php82", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php82.git", + "reference": "5d2ed36f7734637dacc025f179698031951b1692" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692", + "reference": "5d2ed36f7734637dacc025f179698031951b1692", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php82\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php82/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "tbachert/spi", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/Nevay/spi.git", + "reference": "2ddfaf815dafb45791a61b08170de8d583c16062" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nevay/spi/zipball/2ddfaf815dafb45791a61b08170de8d583c16062", + "reference": "2ddfaf815dafb45791a61b08170de8d583c16062", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "composer/semver": "^1.0 || ^2.0 || ^3.0", + "php": "^8.1" + }, + "require-dev": { + "composer/composer": "^2.0", + "infection/infection": "^0.27.9", + "phpunit/phpunit": "^10.5", + "psalm/phar": "^5.18" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-main": "0.2.x-dev" + }, + "class": "Nevay\\SPI\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Nevay\\SPI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Service provider loading facility", + "keywords": [ + "service provider" + ], + "support": { + "issues": "https://github.com/Nevay/spi/issues", + "source": "https://github.com/Nevay/spi/tree/v1.0.2" + }, + "time": "2024-10-04T16:36:12+00:00" + }, { "name": "thecodingmachine/safe", "version": "v2.5.0", @@ -1623,16 +3328,16 @@ }, { "name": "utopia-php/cli", - "version": "0.15.0", + "version": "0.15.1", "source": { "type": "git", "url": "https://github.com/utopia-php/cli.git", - "reference": "ccb7c8125ffe0254fef8f25744bfa376eb7bd0ea" + "reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cli/zipball/ccb7c8125ffe0254fef8f25744bfa376eb7bd0ea", - "reference": "ccb7c8125ffe0254fef8f25744bfa376eb7bd0ea", + "url": "https://api.github.com/repos/utopia-php/cli/zipball/d69bbe51a6a94dc4e5bcdd542b5938038b985a65", + "reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65", "shasum": "" }, "require": { @@ -1666,9 +3371,55 @@ ], "support": { "issues": "https://github.com/utopia-php/cli/issues", - "source": "https://github.com/utopia-php/cli/tree/0.15.0" + "source": "https://github.com/utopia-php/cli/tree/0.15.1" }, - "time": "2023-03-01T05:55:14+00:00" + "time": "2024-10-04T13:55:36+00:00" + }, + { + "name": "utopia-php/compression", + "version": "0.1.2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/compression.git", + "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", + "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpunit/phpunit": "^9.3", + "vimeo/psalm": "4.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Compression\\": "src/Compression" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A simple Compression library to handle file compression", + "keywords": [ + "compression", + "framework", + "php", + "upf", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/compression/issues", + "source": "https://github.com/utopia-php/compression/tree/0.1.2" + }, + "time": "2024-11-08T14:59:54+00:00" }, { "name": "utopia-php/config", @@ -1925,20 +3676,22 @@ }, { "name": "utopia-php/framework", - "version": "0.33.8", + "version": "0.33.12", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "a7f577540a25cb90896fef2b64767bf8d700f3c5" + "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/a7f577540a25cb90896fef2b64767bf8d700f3c5", - "reference": "a7f577540a25cb90896fef2b64767bf8d700f3c5", + "url": "https://api.github.com/repos/utopia-php/http/zipball/bfb7812df9e489b3cba7d5504a49ce578c71af1f", + "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f", "shasum": "" }, "require": { - "php": ">=8.0" + "php": ">=8.1", + "utopia-php/compression": "0.1.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "^1.2", @@ -1964,9 +3717,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.8" + "source": "https://github.com/utopia-php/http/tree/0.33.12" }, - "time": "2024-08-15T14:10:09+00:00" + "time": "2024-11-13T12:45:45+00:00" }, { "name": "utopia-php/image", @@ -2069,16 +3822,16 @@ }, { "name": "utopia-php/logger", - "version": "0.6.0", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/logger.git", - "reference": "a2d1daeeb8f61fdec6d851950d9a021a3d05c9f9" + "reference": "25b5bd2ad8bb51292f76332faa7034644fd0941d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/logger/zipball/a2d1daeeb8f61fdec6d851950d9a021a3d05c9f9", - "reference": "a2d1daeeb8f61fdec6d851950d9a021a3d05c9f9", + "url": "https://api.github.com/repos/utopia-php/logger/zipball/25b5bd2ad8bb51292f76332faa7034644fd0941d", + "reference": "25b5bd2ad8bb51292f76332faa7034644fd0941d", "shasum": "" }, "require": { @@ -2117,22 +3870,22 @@ ], "support": { "issues": "https://github.com/utopia-php/logger/issues", - "source": "https://github.com/utopia-php/logger/tree/0.6.0" + "source": "https://github.com/utopia-php/logger/tree/0.6.2" }, - "time": "2024-05-23T13:37:54+00:00" + "time": "2024-10-14T16:02:49+00:00" }, { "name": "utopia-php/messaging", - "version": "0.12.0", + "version": "0.12.2", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "6e466d3511981291843c6ebf9ce3f44fc75e37b0" + "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/6e466d3511981291843c6ebf9ce3f44fc75e37b0", - "reference": "6e466d3511981291843c6ebf9ce3f44fc75e37b0", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/f6790fba1fcee12163d51c65d2c226a7856295d9", + "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9", "shasum": "" }, "require": { @@ -2168,22 +3921,22 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.12.0" + "source": "https://github.com/utopia-php/messaging/tree/0.12.2" }, - "time": "2024-05-30T14:58:25+00:00" + "time": "2024-10-22T01:02:20+00:00" }, { "name": "utopia-php/migration", - "version": "0.5.2", + "version": "0.5.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "f18d44d4459f78c292dac9edde856fd156fe497a" + "reference": "b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/f18d44d4459f78c292dac9edde856fd156fe497a", - "reference": "f18d44d4459f78c292dac9edde856fd156fe497a", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6", + "reference": "b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6", "shasum": "" }, "require": { @@ -2216,9 +3969,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.5.2" + "source": "https://github.com/utopia-php/migration/tree/0.5.3" }, - "time": "2024-07-22T09:27:07+00:00" + "time": "2024-09-10T10:45:18+00:00" }, { "name": "utopia-php/mongo", @@ -2332,16 +4085,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.0", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "beeea0f2c9bce14a6869fc5c87a1047cdecb5c52" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/beeea0f2c9bce14a6869fc5c87a1047cdecb5c52", - "reference": "beeea0f2c9bce14a6869fc5c87a1047cdecb5c52", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -2376,9 +4129,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.0" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2024-05-08T17:00:55+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", @@ -2486,22 +4239,23 @@ }, { "name": "utopia-php/queue", - "version": "0.7.0", + "version": "0.7.3", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "917565256eb94bcab7246f7a746b1a486813761b" + "reference": "16074a98ee7d6212bc1228de200e13db470c098a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/917565256eb94bcab7246f7a746b1a486813761b", - "reference": "917565256eb94bcab7246f7a746b1a486813761b", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/16074a98ee7d6212bc1228de200e13db470c098a", + "reference": "16074a98ee7d6212bc1228de200e13db470c098a", "shasum": "" }, "require": { - "php": ">=8.0", + "php": ">=8.1", "utopia-php/cli": "0.15.*", - "utopia-php/framework": "0.*.*" + "utopia-php/framework": "0.*.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "^0.2.3", @@ -2541,9 +4295,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.7.0" + "source": "https://github.com/utopia-php/queue/tree/0.7.3" }, - "time": "2024-01-17T19:00:43+00:00" + "time": "2024-11-13T12:47:48+00:00" }, { "name": "utopia-php/registry", @@ -2599,16 +4353,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.5", + "version": "0.18.6", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "7d355c5e3ccc8ecebc0266f8ddd30088a43be919" + "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/7d355c5e3ccc8ecebc0266f8ddd30088a43be919", - "reference": "7d355c5e3ccc8ecebc0266f8ddd30088a43be919", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/893ccf06e183f8ece2aed8dbf14d64d6ba036071", + "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071", "shasum": "" }, "require": { @@ -2648,9 +4402,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.5" + "source": "https://github.com/utopia-php/storage/tree/0.18.6" }, - "time": "2024-09-04T08:57:27+00:00" + "time": "2024-11-06T09:58:50+00:00" }, { "name": "utopia-php/swoole", @@ -2759,6 +4513,56 @@ }, "time": "2024-04-01T10:22:28+00:00" }, + { + "name": "utopia-php/telemetry", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/telemetry.git", + "reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/telemetry/zipball/d35f2f0632f4ee0be63fb7ace6a94a6adda71a80", + "reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80", + "shasum": "" + }, + "require": { + "ext-opentelemetry": "*", + "ext-protobuf": "*", + "nyholm/psr7": "^1.8", + "open-telemetry/exporter-otlp": "^1.1", + "open-telemetry/sdk": "^1.1", + "php": ">=8.0", + "symfony/http-client": "^7.1" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "keywords": [ + "framework", + "php", + "upf" + ], + "support": { + "issues": "https://github.com/utopia-php/telemetry/issues", + "source": "https://github.com/utopia-php/telemetry/tree/0.1.0" + }, + "time": "2024-11-13T10:29:53+00:00" + }, { "name": "utopia-php/vcs", "version": "0.8.2", @@ -2993,16 +4797,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.21", + "version": "0.39.25", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "9754b190d33aaad56fdb8defc94f90248184c5ac" + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/9754b190d33aaad56fdb8defc94f90248184c5ac", - "reference": "9754b190d33aaad56fdb8defc94f90248184c5ac", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5b5323636a8d75a1c4faaae9728098dd6a6a47d1", + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1", "shasum": "" }, "require": { @@ -3010,7 +4814,7 @@ "ext-json": "*", "ext-mbstring": "*", "matthiasmullie/minify": "1.3.*", - "php": ">=8.0", + "php": ">=8.3", "twig/twig": "3.14.*" }, "require-dev": { @@ -3038,9 +4842,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.21" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.25" }, - "time": "2024-09-10T08:49:29+00:00" + "time": "2024-11-08T10:16:34+00:00" }, { "name": "doctrine/annotations", @@ -3314,16 +5118,16 @@ }, { "name": "laravel/pint", - "version": "v1.17.3", + "version": "v1.18.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "9d77be916e145864f10788bb94531d03e1f7b482" + "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/9d77be916e145864f10788bb94531d03e1f7b482", - "reference": "9d77be916e145864f10788bb94531d03e1f7b482", + "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", "shasum": "" }, "require": { @@ -3376,7 +5180,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-03T15:00:28+00:00" + "time": "2024-09-24T17:22:50+00:00" }, { "name": "matthiasmullie/minify", @@ -3504,16 +5308,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -3552,7 +5356,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -3560,20 +5364,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nikic/php-parser", - "version": "v5.2.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", - "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -3616,9 +5420,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-09-15T16:40:33+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "phar-io/manifest", @@ -3838,6 +5642,7 @@ "issues": "https://github.com/phpbench/dom/issues", "source": "https://github.com/phpbench/dom/tree/0.3.3" }, + "abandoned": true, "time": "2023-03-06T23:46:57+00:00" }, { @@ -3994,16 +5799,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c", + "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c", "shasum": "" }, "require": { @@ -4012,17 +5817,17 @@ "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", + "mockery/mockery": "~1.3.5 || ~1.6.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "psalm/phar": "^5.26" }, "type": "library", "extra": { @@ -4052,29 +5857,29 @@ "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.4.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.0" }, - "time": "2024-05-21T05:55:05+00:00" + "time": "2024-11-12T11:25:25+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { "ext-tokenizer": "*", @@ -4110,9 +5915,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpspec/prophecy", @@ -4185,30 +5990,30 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.30.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "51b95ec8670af41009e2b2b56873bad96682413e" + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/51b95ec8670af41009e2b2b56873bad96682413e", - "reference": "51b95ec8670af41009e2b2b56873bad96682413e", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -4226,9 +6031,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.30.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" }, - "time": "2024-09-07T20:13:05+00:00" + "time": "2024-10-13T11:29:49+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4701,109 +6506,6 @@ }, "time": "2021-02-03T23:26:27+00:00" }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -5865,16 +7567,16 @@ }, { "name": "symfony/console", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", - "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", "shasum": "" }, "require": { @@ -5938,7 +7640,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.4" + "source": "https://github.com/symfony/console/tree/v7.1.8" }, "funding": [ { @@ -5954,87 +7656,20 @@ "type": "tidelift" } ], - "time": "2024-08-15T22:48:53+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.2", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", "shasum": "" }, "require": { @@ -6071,7 +7706,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.2" + "source": "https://github.com/symfony/filesystem/tree/v7.1.6" }, "funding": [ { @@ -6087,20 +7722,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-10-25T15:11:02+00:00" }, { "name": "symfony/finder", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { @@ -6135,7 +7770,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.4" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -6151,20 +7786,20 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" + "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", - "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85", + "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85", "shasum": "" }, "require": { @@ -6202,7 +7837,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" + "source": "https://github.com/symfony/options-resolver/tree/v7.1.6" }, "funding": [ { @@ -6218,7 +7853,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6536,16 +8171,16 @@ }, { "name": "symfony/process", - "version": "v7.1.3", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca" + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca", - "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", "shasum": "" }, "require": { @@ -6577,7 +8212,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.3" + "source": "https://github.com/symfony/process/tree/v7.1.8" }, "funding": [ { @@ -6593,103 +8228,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:44:47+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/string", - "version": "v7.1.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", - "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", "shasum": "" }, "require": { @@ -6747,7 +8299,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.4" + "source": "https://github.com/symfony/string/tree/v7.1.8" }, "funding": [ { @@ -6763,7 +8315,7 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:59:40+00:00" + "time": "2024-11-13T13:31:21+00:00" }, { "name": "textalk/websocket", @@ -6866,16 +8418,16 @@ }, { "name": "twig/twig", - "version": "v3.14.0", + "version": "v3.14.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72" + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", "shasum": "" }, "require": { @@ -6929,7 +8481,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.0" + "source": "https://github.com/twigphp/Twig/tree/v3.14.2" }, "funding": [ { @@ -6941,7 +8493,7 @@ "type": "tidelift" } ], - "time": "2024-09-09T17:55:12+00:00" + "time": "2024-11-07T12:36:22+00:00" }, { "name": "webmozart/glob", diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index 65d2f7717c..6e37f270a4 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -25,6 +25,9 @@ use Appwrite\Spec\Swagger2; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Platform\Action; +use Utopia\Validator\Nullable; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; class SDKs extends Action { @@ -37,23 +40,35 @@ class SDKs extends Action { $this ->desc('Generate Appwrite SDKs') - ->callback(fn () => $this->action()); + ->param('platform', null, new Nullable(new Text(256)), 'Selected Platform', optional: true) + ->param('sdk', null, new Nullable(new Text(256)), 'Selected SDK', optional:true) + ->param('version', null, new Nullable(new Text(256)), 'Selected SDK', optional:true) + ->param('git', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we use git push?', optional: true) + ->param('production', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to production?', optional:true) + ->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional:true) + ->callback([$this, 'action']); } - public function action(): void + public function action(?string $selectedPlatform, ?string $selectedSDK, ?string $version, ?string $git, ?string $production, ?string $message) { - $platforms = Config::getParam('platforms'); - $selectedPlatform = Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); - $selectedSDK = \strtolower(Console::confirm('Choose SDK ("*" for all):')); - $version = Console::confirm('Choose an Appwrite version'); - $git = (Console::confirm('Should we use git push? (yes/no)') == 'yes'); - $production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false; - $message = ($git) ? Console::confirm('Please enter your commit message:') : ''; + $selectedPlatform ??= Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); + $selectedSDK ??= \strtolower(Console::confirm('Choose SDK ("*" for all):')); + $version ??= Console::confirm('Choose an Appwrite version'); + + $git ??= Console::confirm('Should we use git push? (yes/no)'); + $git = $git === 'yes'; + + if ($git) { + $production ??= Console::confirm('Type "Appwrite" to push code to production git repos'); + $production = $production === 'Appwrite'; + $message ??= Console::confirm('Please enter your commit message:'); + } if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', '1.4.x', '1.5.x', '1.6.x', 'latest'])) { throw new \Exception('Unknown version given'); } + $platforms = Config::getParam('platforms'); foreach ($platforms as $key => $platform) { if ($selectedPlatform !== $key && $selectedPlatform !== '*') { continue; diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 3074d59b7c..a8da75eea0 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -323,6 +323,7 @@ class OpenAPI3 extends Format case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': + case 'Appwrite\Functions\Validator\Payload': $param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default']; $node['schema']['type'] = 'object'; $node['schema']['x-example'] = '{}'; diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 2eab7807b3..6cb4986710 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -336,6 +336,7 @@ class Swagger2 extends Format case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': + case 'Appwrite\Functions\Validator\Payload': $node['type'] = 'object'; $node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default']; $node['x-example'] = '{}'; From 842e23220ae3250f502be62a3e9c9cb974e2fc6b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 19 Nov 2024 07:51:50 +0545 Subject: [PATCH 034/340] update project last activity on error hook --- app/controllers/general.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 0bbfa2b694..f7f15138a6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -702,6 +702,22 @@ App::error() ->inject('log') ->inject('queueForUsage') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { + /** + * Update project last activity + */ + if (!$project->isEmpty() && $project->getId() !== 'console') { + try { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + } + } catch(Throwable $th) { + Console::error('[Error] updating project\'s last activity'); + Console::error($th->getMessage()); + } + } + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); From e8079cfd295a5423639a0e4babba6773c1136e65 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 19 Nov 2024 06:59:30 +0000 Subject: [PATCH 035/340] lint --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f7f15138a6..4bf45f3860 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -712,7 +712,7 @@ App::error() $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); } - } catch(Throwable $th) { + } catch (Throwable $th) { Console::error('[Error] updating project\'s last activity'); Console::error($th->getMessage()); } From 877a978451374589a2f64bd50d41380732c64b2b Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Tue, 19 Nov 2024 16:42:16 +0100 Subject: [PATCH 036/340] chore: update base to 0.9.5 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 07295f4afb..41810f5dc4 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM appwrite/base:0.9.3 AS final +FROM appwrite/base:0.9.5 AS final LABEL maintainer="team@appwrite.io" From 5f56c45c6cdc1ccaa1f404bae1bb9e5c51e82e12 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 19 Nov 2024 16:47:14 +0100 Subject: [PATCH 037/340] fix: team invites with existing session --- app/controllers/api/teams.php | 101 +++++++++++-------- tests/e2e/Services/Teams/TeamsBaseClient.php | 74 +++++++++++++- 2 files changed, 130 insertions(+), 45 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index ba1858c5aa..1e15e4b81b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1060,7 +1060,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } - if ($user->isEmpty()) { + $hasSession = !$user->isEmpty(); + if (!$hasSession) { $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } @@ -1079,39 +1080,64 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); - // Log user in + // Create session for the user if not logged in + if (!$hasSession) { + Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::user($user->getId())->toString()); + $detector = new Detector($request->getUserAgent('UNKNOWN')); + $record = $geodb->get($request->getIP()); + $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; + $expire = DateTime::addSeconds(new \DateTime(), $authDuration); + $secret = Auth::tokenGenerator(); + $session = new Document(array_merge([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'provider' => Auth::SESSION_PROVIDER_EMAIL, + 'providerUid' => $user->getAttribute('email'), + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak + 'userAgent' => $request->getUserAgent('UNKNOWN'), + 'ip' => $request->getIP(), + 'factors' => ['email'], + 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', + 'expire' => DateTime::addSeconds(new \DateTime(), $authDuration) + ], $detector->getOS(), $detector->getClient(), $detector->getDevice())); - $detector = new Detector($request->getUserAgent('UNKNOWN')); - $record = $geodb->get($request->getIP()); - $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; - $expire = DateTime::addSeconds(new \DateTime(), $authDuration); - $secret = Auth::tokenGenerator(); - $session = new Document(array_merge([ - '$id' => ID::unique(), - 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), - 'provider' => Auth::SESSION_PROVIDER_EMAIL, - 'providerUid' => $user->getAttribute('email'), - 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak - 'userAgent' => $request->getUserAgent('UNKNOWN'), - 'ip' => $request->getIP(), - 'factors' => ['email'], - 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', - 'expire' => DateTime::addSeconds(new \DateTime(), $authDuration) - ], $detector->getOS(), $detector->getClient(), $detector->getDevice())); + $session = $dbForProject->createDocument('sessions', $session); - $session = $dbForProject->createDocument('sessions', $session - ->setAttribute('$permissions', [ - Permission::read(Role::user($user->getId())), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ])); + Authorization::setRole(Role::user($userId)->toString()); - $dbForProject->purgeCachedDocument('users', $user->getId()); + if (!Config::getParam('domainVerification')) { + $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); + } - Authorization::setRole(Role::user($userId)->toString()); + $response + ->addCookie( + name: Auth::$cookieName . '_legacy', + value: Auth::encodeSession($user->getId(), $secret), + expire: (new \DateTime($expire))->getTimestamp(), + path:'/', + domain: Config::getParam('cookieDomain'), + secure: ('https' === $protocol), + httponly:true + ) + ->addCookie( + name:Auth::$cookieName, + value:Auth::encodeSession($user->getId(), $secret), + expire: (new \DateTime($expire))->getTimestamp(), + path:'/', + domain:Config::getParam('cookieDomain'), + secure:('https' === $protocol), + httponly:true, + sameSite: Config::getParam('cookieSamesite') + ) + ; + } $membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership); @@ -1125,22 +1151,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->setParam('membershipId', $membership->getId()) ; - if (!Config::getParam('domainVerification')) { - $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) - ; - } - - $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) - ; - $response->dynamic( $membership - ->setAttribute('teamName', $team->getAttribute('name')) - ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')), + ->setAttribute('teamName', $team->getAttribute('name')) + ->setAttribute('userName', $user->getAttribute('name')) + ->setAttribute('userEmail', $user->getAttribute('email')), Response::MODEL_MEMBERSHIP ); }); diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 9188575932..ca6082f6d0 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -559,6 +559,76 @@ trait TeamsBaseClient return $data; } + + /** + * @depends testCreateTeam + */ + public function testUpdateMembershipWithSession(array $data): void + { + $teamUid = $data['teamUid'] ?? ''; + + // create user + $response = $this->client->call(Client::METHOD_POST, '/account', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'userId' => 'unique()', + 'email' => uniqid() . 'foe@localhost.test', + 'password' => 'password', + 'name' => 'test' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $user = $response['body']; + + // create session + $response = $this->client->call(Client::METHOD_POST, '/account/sessions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $user['email'], + 'password' => 'password' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $session = $response['cookies']['a_session_' . $this->getProject()['$id']]; + + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'email' => $user['email'], + 'roles' => ['developer'], + 'url' => 'http://localhost:5000/join-us#title' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $lastEmail = $this->getLastEmail(); + + $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); + $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); + + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ + 'secret' => $secret, + 'userId' => $userUid, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertNotEmpty($response['body']['userId']); + $this->assertNotEmpty($response['body']['teamId']); + $this->assertCount(1, $response['body']['roles']); + $this->assertEmpty($response['cookies']); + } + /** * @depends testUpdateTeamMembership */ @@ -648,7 +718,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(3, $response['body']['total']); + $this->assertEquals(4, $response['body']['total']); $ownerMembershipUid = $response['body']['memberships'][0]['$id']; @@ -703,7 +773,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, $response['body']['total']); + $this->assertEquals(3, $response['body']['total']); /** * Test for when the owner tries to delete their membership From c97a94ec984243462435f919274a1374495eb0f1 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 19 Nov 2024 16:50:31 +0100 Subject: [PATCH 038/340] chore: run formatter --- app/controllers/api/teams.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 1e15e4b81b..f829800b98 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1121,19 +1121,19 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') name: Auth::$cookieName . '_legacy', value: Auth::encodeSession($user->getId(), $secret), expire: (new \DateTime($expire))->getTimestamp(), - path:'/', + path: '/', domain: Config::getParam('cookieDomain'), secure: ('https' === $protocol), - httponly:true + httponly: true ) ->addCookie( - name:Auth::$cookieName, - value:Auth::encodeSession($user->getId(), $secret), + name: Auth::$cookieName, + value: Auth::encodeSession($user->getId(), $secret), expire: (new \DateTime($expire))->getTimestamp(), - path:'/', - domain:Config::getParam('cookieDomain'), - secure:('https' === $protocol), - httponly:true, + path: '/', + domain: Config::getParam('cookieDomain'), + secure: ('https' === $protocol), + httponly: true, sameSite: Config::getParam('cookieSamesite') ) ; From 2da2b5bb7fe2423c6f14639d17496bb46daf0151 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 20 Nov 2024 04:25:37 +0000 Subject: [PATCH 039/340] reset error hook --- app/controllers/general.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 4bf45f3860..0bbfa2b694 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -702,22 +702,6 @@ App::error() ->inject('log') ->inject('queueForUsage') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { - /** - * Update project last activity - */ - if (!$project->isEmpty() && $project->getId() !== 'console') { - try { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); - } - } catch (Throwable $th) { - Console::error('[Error] updating project\'s last activity'); - Console::error($th->getMessage()); - } - } - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); From c33c5732e0758a5c9413292dc1b9af925e60c285 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 20 Nov 2024 04:29:57 +0000 Subject: [PATCH 040/340] move accessed at to init --- app/controllers/shared/api.php | 63 ++++++++++++++++------------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 6d87940ff7..a78bf1d88f 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -155,12 +155,13 @@ App::init() ->inject('utopia') ->inject('request') ->inject('dbForConsole') + ->inject('dbForProject') ->inject('project') ->inject('user') ->inject('session') ->inject('servers') ->inject('mode') - ->action(function (App $utopia, Request $request, Database $dbForConsole, Document $project, Document $user, ?Document $session, array $servers, string $mode) { + ->action(function (App $utopia, Request $request, Database $dbForConsole, Database $dbForProject, Document $project, Document $user, ?Document $session, array $servers, string $mode) { $route = $utopia->getRoute(); if ($project->isEmpty()) { @@ -301,6 +302,33 @@ App::init() Authorization::setRole($authRole); } + /** + * Update project last activity + */ + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + } + } + + /** + * Update user last activity + */ + if (!$user->isEmpty()) { + $accessedAt = $user->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { + $user->setAttribute('accessedAt', DateTime::now()); + + if (APP_MODE_ADMIN !== $mode) { + $dbForProject->updateDocument('users', $user->getId(), $user); + } else { + $dbForConsole->updateDocument('users', $user->getId(), $user); + } + } + } + $service = $route->getLabel('sdk.namespace', ''); if (!empty($service)) { if ( @@ -588,9 +616,7 @@ App::shutdown() ->inject('queueForMessaging') ->inject('dbForProject') ->inject('queueForFunctions') - ->inject('mode') - ->inject('dbForConsole') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Database $dbForProject, Func $queueForFunctions, string $mode, Database $dbForConsole) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Database $dbForProject, Func $queueForFunctions) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -746,8 +772,6 @@ App::shutdown() } } - - if ($project->getId() !== 'console') { if (!Auth::isPrivilegedUser(Authorization::getRoles())) { $fileSize = 0; @@ -766,33 +790,6 @@ App::shutdown() ->setProject($project) ->trigger(); } - - /** - * Update project last activity - */ - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); - } - } - - /** - * Update user last activity - */ - if (!$user->isEmpty()) { - $accessedAt = $user->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { - $user->setAttribute('accessedAt', DateTime::now()); - - if (APP_MODE_ADMIN !== $mode) { - $dbForProject->updateDocument('users', $user->getId(), $user); - } else { - $dbForConsole->updateDocument('users', $user->getId(), $user); - } - } - } }); App::init() From 15a5f8690d78e5e5b2abe229e6af64ad3d725ec9 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 20 Nov 2024 11:33:38 +0100 Subject: [PATCH 041/340] sync: 1.6.x with main --- .gitignore | 3 --- app/config/specs/open-api3-latest-client.json | 8 ++----- .../specs/open-api3-latest-console.json | 22 ++++++++---------- app/config/specs/open-api3-latest-server.json | 8 ++----- app/config/specs/swagger2-latest-client.json | 9 +------- app/config/specs/swagger2-latest-console.json | 23 +++++++------------ app/config/specs/swagger2-latest-server.json | 9 +------- 7 files changed, 23 insertions(+), 59 deletions(-) diff --git a/.gitignore b/.gitignore index 41c6cb8fb8..b2aba0a863 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,4 @@ dev/yasd_init.php Makefile appwrite.json <<<<<<< HEAD -.zed/ -======= /.zed/ ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index ec470c2106..d948a101f2 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -2784,7 +2784,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -5082,13 +5082,9 @@ "type": "object", "properties": { "body": { - "type": "object", + "type": "string", "description": "HTTP body of execution. Default value is empty string.", -<<<<<<< HEAD "x-example": "" -======= - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index b7cb787031..fb01509ecd 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -2795,7 +2795,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -11070,13 +11070,9 @@ "type": "object", "properties": { "body": { - "type": "object", + "type": "string", "description": "HTTP body of execution. Default value is empty string.", -<<<<<<< HEAD "x-example": "" -======= - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", @@ -20676,7 +20672,7 @@ }, "\/projects\/{projectId}\/auth\/memberships-privacy": { "patch": { - "summary": "Update project team sensitive attributes", + "summary": "Update project memberships privacy attributes", "operationId": "projectsUpdateMembershipsPrivacy", "tags": [ "projects" @@ -36081,17 +36077,17 @@ "description": "Whether or not to send session alert emails to users.", "x-example": true }, - "membershipsUserName": { + "authMembershipsUserName": { "type": "boolean", "description": "Whether or not to show user names in the teams membership response.", "x-example": true }, - "membershipsUserEmail": { + "authMembershipsUserEmail": { "type": "boolean", "description": "Whether or not to show user emails in the teams membership response.", "x-example": true }, - "membershipsMfa": { + "authMembershipsMfa": { "type": "boolean", "description": "Whether or not to show user MFA status in the teams membership response.", "x-example": true @@ -36301,9 +36297,9 @@ "authPersonalDataCheck", "authMockNumbers", "authSessionAlerts", - "membershipsUserName", - "membershipsUserEmail", - "membershipsMfa", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", "oAuthProviders", "platforms", "webhooks", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 0453b7652c..1504322456 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -2451,7 +2451,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -9957,13 +9957,9 @@ "type": "object", "properties": { "body": { - "type": "object", + "type": "string", "description": "HTTP body of execution. Default value is empty string.", -<<<<<<< HEAD "x-example": "" -======= - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index e99495bab3..3ac70ffe28 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -2922,7 +2922,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -5232,17 +5232,10 @@ "type": "object", "properties": { "body": { -<<<<<<< HEAD "type": "string", "description": "HTTP body of execution. Default value is empty string.", "default": "", "x-example": "" -======= - "type": "object", - "description": "HTTP body of execution. Default value is empty string.", - "default": "", - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 96da327cb4..25c0c289b3 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -2949,7 +2949,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -11214,17 +11214,10 @@ "type": "object", "properties": { "body": { -<<<<<<< HEAD "type": "string", "description": "HTTP body of execution. Default value is empty string.", "default": "", "x-example": "" -======= - "type": "object", - "description": "HTTP body of execution. Default value is empty string.", - "default": "", - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", @@ -21145,7 +21138,7 @@ }, "\/projects\/{projectId}\/auth\/memberships-privacy": { "patch": { - "summary": "Update project team sensitive attributes", + "summary": "Update project memberships privacy attributes", "operationId": "projectsUpdateMembershipsPrivacy", "consumes": [ "application\/json" @@ -36598,17 +36591,17 @@ "description": "Whether or not to send session alert emails to users.", "x-example": true }, - "membershipsUserName": { + "authMembershipsUserName": { "type": "boolean", "description": "Whether or not to show user names in the teams membership response.", "x-example": true }, - "membershipsUserEmail": { + "authMembershipsUserEmail": { "type": "boolean", "description": "Whether or not to show user emails in the teams membership response.", "x-example": true }, - "membershipsMfa": { + "authMembershipsMfa": { "type": "boolean", "description": "Whether or not to show user MFA status in the teams membership response.", "x-example": true @@ -36822,9 +36815,9 @@ "authPersonalDataCheck", "authMockNumbers", "authSessionAlerts", - "membershipsUserName", - "membershipsUserEmail", - "membershipsMfa", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", "oAuthProviders", "platforms", "webhooks", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 31128e5991..68bcf268fb 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -2604,7 +2604,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -10107,17 +10107,10 @@ "type": "object", "properties": { "body": { -<<<<<<< HEAD "type": "string", "description": "HTTP body of execution. Default value is empty string.", "default": "", "x-example": "" -======= - "type": "object", - "description": "HTTP body of execution. Default value is empty string.", - "default": "", - "x-example": "{}" ->>>>>>> 8e021158286cd04b64b391afe86975e23368a52c }, "async": { "type": "boolean", From 0b11e0cc92032dbe4707b3b9ddb3fa02ddfeb49f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 20 Nov 2024 11:52:27 +0100 Subject: [PATCH 042/340] fix: gitignore merge conflict leftover --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index b2aba0a863..a68af84071 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,4 @@ dev/yasd_init.php .phpunit.result.cache Makefile appwrite.json -<<<<<<< HEAD /.zed/ From f490d4edaf1e93d8021013eb7b7af08b8b9b18f8 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 12 Nov 2024 10:27:24 +0100 Subject: [PATCH 043/340] Merge pull request #8797 from appwrite/feat-migration Feat migration # Conflicts: # composer.lock --- .github/workflows/tests.yml | 15 ++- app/cli.php | 7 +- app/config/errors.php | 2 +- app/controllers/api/databases.php | 9 +- app/controllers/api/projects.php | 103 +++++++++++++----- app/http.php | 5 +- app/init.php | 8 +- app/realtime.php | 4 +- app/worker.php | 12 +- composer.json | 6 +- composer.lock | 52 ++++----- docker-compose.yml | 1 + src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Utopia/Response/Model/Func.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 2 +- 15 files changed, 152 insertions(+), 83 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 29aa9b0581..29b3bdd70d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -127,6 +127,11 @@ jobs: Messaging, Migrations ] + tables-mode: [ + 'Project', + 'Shared V1', + 'Shared V2', + ] steps: - name: checkout @@ -145,11 +150,11 @@ jobs: docker compose up -d sleep 30 - - name: Run ${{matrix.service}} Tests - run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug - - - name: Run ${{matrix.service}} Shared Tables Tests - run: _APP_DATABASE_SHARED_TABLES=database_db_main docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug + - name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode + run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug + env: + _APP_DATABASE_SHARED_TABLES: ${{ matrix.table_mode == 'Shared V1' || matrix.table_mode == 'Shared V2' && 'database_db_main' || '' }} + _APP_DATABASE_SHARED_TABLES_V1: ${{ matrix.table_mode == 'Shared V1' && 'database_db_main' || '' }} benchmarking: name: Benchmark diff --git a/app/cli.php b/app/cli.php index 23502ec402..b0f053d3c6 100644 --- a/app/cli.php +++ b/app/cli.php @@ -114,8 +114,9 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -136,10 +137,10 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$dsn->getHost()] = $database; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) diff --git a/app/config/errors.php b/app/config/errors.php index 3afec4faaf..f09d1596eb 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -686,7 +686,7 @@ return [ ], Exception::ATTRIBUTE_LIMIT_EXCEEDED => [ 'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED, - 'description' => 'The maximum number of attributes has been reached.', + 'description' => 'The maximum number or size of attributes for this collection has been reached.', 'code' => 400, ], Exception::ATTRIBUTE_VALUE_INVALID => [ diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4dfaf0cd5c..a00324f3b7 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -152,7 +152,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (DuplicateException) { throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); @@ -196,7 +196,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { $dbForProject->deleteDocument('attributes', $attribute->getId()); - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); @@ -392,6 +392,8 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); } catch (NotFoundException) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } } @@ -2631,7 +2633,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $validator = new IndexValidator( $collection->getAttribute('attributes'), - $dbForProject->getAdapter()->getMaxIndexLength() + $dbForProject->getAdapter()->getMaxIndexLength(), + $dbForProject->getAdapter()->getInternalIndexesKeys(), ); if (!$validator->isValid($index)) { throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index df8b1cb07b..39300a2d4a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -122,6 +122,10 @@ App::post('/v1/projects') $projectId = ($projectId == 'unique()') ? ID::unique() : $projectId; + if ($projectId === 'console') { + throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); + } + $databases = Config::getParam('pools-database', []); $databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE'); @@ -132,16 +136,14 @@ App::post('/v1/projects') $dsn = $databases[array_rand($databases)]; } - if ($projectId === 'console') { - throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); - } - // TODO: Temporary until all projects are using shared tables. - if ($dsn === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn, $sharedTables)) { $schema = 'appwrite'; $database = 'appwrite'; $namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); - $dsn = $schema . '://' . System::getEnv('_APP_DATABASE_SHARED_TABLES', '') . '?database=' . $database; + $dsn = $schema . '://' . $dsn . '?database=' . $database; if (!empty($namespace)) { $dsn .= '&namespace=' . $namespace; @@ -195,11 +197,18 @@ App::post('/v1/projects') $adapter = $pools->get($dsn->getHost())->pop()->getResource(); $dbForProject = new Database($adapter, $cache); + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $projectTables = !\in_array($dsn->getHost(), $sharedTables); + $sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1); + $sharedTablesV2 = !$projectTables && !$sharedTablesV1; + $sharedTables = $sharedTablesV1 || $sharedTablesV2; + + if ($sharedTables) { $dbForProject ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject @@ -208,34 +217,70 @@ App::post('/v1/projects') ->setNamespace('_' . $project->getInternalId()); } - $dbForProject->create(); + $create = true; - $audit = new Audit($dbForProject); - $audit->setup(); + try { + $dbForProject->create(); + } catch (Duplicate) { + $create = false; + } - $abuse = new TimeLimit('', 0, 1, $dbForProject); - $abuse->setup(); + if ($create || $projectTables) { + $audit = new Audit($dbForProject); + $audit->setup(); - /** @var array $collections */ - $collections = Config::getParam('collections', [])['projects'] ?? []; + $abuse = new TimeLimit('', 0, 1, $dbForProject); + $abuse->setup(); + } - foreach ($collections as $key => $collection) { - if (($collection['$collection'] ?? '') !== Database::METADATA) { - continue; - } + if (!$create && $sharedTablesV1) { + $attributes = \array_map(fn ($attribute) => new Document($attribute), Audit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), Audit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('audit'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'audit', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); - $attributes = \array_map(function (array $attribute) { - return new Document($attribute); - }, $collection['attributes']); + $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('abuse'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'abuse', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } - $indexes = \array_map(function (array $index) { - return new Document($index); - }, $collection['indexes']); + if ($create || $sharedTablesV1) { + /** @var array $collections */ + $collections = Config::getParam('collections', [])['projects'] ?? []; - try { - $dbForProject->createCollection($key, $attributes, $indexes); - } catch (Duplicate) { - // Collection already exists + foreach ($collections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } + + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); + + try { + $dbForProject->createCollection($key, $attributes, $indexes); + } catch (Duplicate) { + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom($key), + '$permissions' => [Permission::create(Role::any())], + 'name' => $key, + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } } } diff --git a/app/http.php b/app/http.php index 641143694d..41f6283156 100644 --- a/app/http.php +++ b/app/http.php @@ -16,6 +16,7 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -93,7 +94,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg try { Console::success('[Setup] - Creating database: appwrite...'); $dbForConsole->create(); - } catch (\Throwable $e) { + } catch (Duplicate) { Console::success('[Setup] - Skip: metadata table already exists'); } @@ -225,7 +226,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg }); }); -$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) { +$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) { App::setResource('swooleRequest', fn () => $swooleRequest); App::setResource('swooleResponse', fn () => $swooleResponse); diff --git a/app/init.php b/app/init.php index c9ec2e0061..3744bb055c 100644 --- a/app/init.php +++ b/app/init.php @@ -1432,7 +1432,9 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -1487,7 +1489,9 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) diff --git a/app/realtime.php b/app/realtime.php index 15635058cf..cfb9bf9a16 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -93,7 +93,9 @@ if (!function_exists('getProjectDB')) { $database = new Database($adapter, getCache()); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) diff --git a/app/worker.php b/app/worker.php index 6b7aba5c1b..7899c1d5bc 100644 --- a/app/worker.php +++ b/app/worker.php @@ -93,7 +93,9 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -126,7 +128,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -150,7 +154,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$dsn->getHost()] = $database; - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) diff --git a/composer.json b/composer.json index 99f696e116..e3fbcabc83 100644 --- a/composer.json +++ b/composer.json @@ -45,13 +45,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.43.0", + "utopia-php/abuse": "0.43.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.43.0", + "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.16", + "utopia-php/database": "0.53.20", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 3b4ed6e206..87d8b47583 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": "c56db8736d679aff6e2b275ec59f1dbf", + "content-hash": "ae3b9a491c9870a4897cdf712caba1e3", "packages": [ { "name": "adhocore/jwt", @@ -3135,16 +3135,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.0", + "version": "0.43.1", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6" + "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/6346a3b4c5177a43160035a7289e30fdfb0790d6", - "reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/e404c21e8dcf6a310bc83cf1d74e716b105598fa", + "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa", "shasum": "" }, "require": { @@ -3180,9 +3180,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.0" + "source": "https://github.com/utopia-php/abuse/tree/0.43.1" }, - "time": "2024-08-30T05:17:23+00:00" + "time": "2024-10-23T04:29:12+00:00" }, { "name": "utopia-php/analytics", @@ -3232,16 +3232,16 @@ }, { "name": "utopia-php/audit", - "version": "0.43.0", + "version": "0.43.1", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e" + "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", - "reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/04a47dd1f5f92e2d50e971a06bcc9e759325d277", + "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277", "shasum": "" }, "require": { @@ -3273,9 +3273,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.43.0" + "source": "https://github.com/utopia-php/audit/tree/0.43.1" }, - "time": "2024-08-30T05:17:36+00:00" + "time": "2024-10-23T04:27:59+00:00" }, { "name": "utopia-php/cache", @@ -3475,16 +3475,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.16", + "version": "0.53.20", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "6661edffeef05b59e16d102b989a72f7f78cf7de" + "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/6661edffeef05b59e16d102b989a72f7f78cf7de", - "reference": "6661edffeef05b59e16d102b989a72f7f78cf7de", + "url": "https://api.github.com/repos/utopia-php/database/zipball/e43f8ee26e06ee8812737e63642dbd7ee7c9dc04", + "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04", "shasum": "" }, "require": { @@ -3525,9 +3525,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.16" + "source": "https://github.com/utopia-php/database/tree/0.53.20" }, - "time": "2024-11-06T03:07:16+00:00" + "time": "2024-11-12T00:23:36+00:00" }, { "name": "utopia-php/domains", @@ -3677,16 +3677,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.13", + "version": "0.33.14", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "4ecab88e424a136ffaa27cdf3db3c60f76c777e4" + "reference": "45a5a2db3602fa054096f378482c7da9936f5850" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/4ecab88e424a136ffaa27cdf3db3c60f76c777e4", - "reference": "4ecab88e424a136ffaa27cdf3db3c60f76c777e4", + "url": "https://api.github.com/repos/utopia-php/http/zipball/45a5a2db3602fa054096f378482c7da9936f5850", + "reference": "45a5a2db3602fa054096f378482c7da9936f5850", "shasum": "" }, "require": { @@ -3718,9 +3718,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.13" + "source": "https://github.com/utopia-php/http/tree/0.33.14" }, - "time": "2024-11-15T08:37:31+00:00" + "time": "2024-11-20T12:39:10+00:00" }, { "name": "utopia-php/image", @@ -8557,7 +8557,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docker-compose.yml b/docker-compose.yml index 048178e60a..0f3f05847c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -193,6 +193,7 @@ services: - _APP_EXPERIMENT_LOGGING_PROVIDER - _APP_EXPERIMENT_LOGGING_CONFIG - _APP_DATABASE_SHARED_TABLES + - _APP_DATABASE_SHARED_TABLES_V1 appwrite-console: <<: *x-logging diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 48e4014f1e..700a480065 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -494,12 +494,13 @@ class Deletes extends Action ]; $limit = \count($projectCollectionIds) + 25; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); while (true) { $collections = $dbForProject->listCollections($limit); foreach ($collections as $collection) { - if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '') || !\in_array($collection->getId(), $projectCollectionIds)) { + if (\in_array($dsn->getHost(), $sharedTables) || !\in_array($collection->getId(), $projectCollectionIds)) { try { $dbForProject->deleteCollection($collection->getId()); } catch (Throwable $e) { @@ -517,7 +518,7 @@ class Deletes extends Action } } - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections); if (empty(\array_diff($collectionsIds, $projectCollectionIds))) { @@ -571,7 +572,7 @@ class Deletes extends Action ], $dbForConsole); // Delete metadata table - if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $dbForProject->deleteCollection('_metadata'); } else { $this->deleteByGroup('_metadata', [], $dbForProject); diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index f4ff214d0b..ab2d7ba051 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -94,7 +94,7 @@ class Func extends Model ]) ->addRule('schedule', [ 'type' => self::TYPE_STRING, - 'description' => 'Function execution schedult in CRON format.', + 'description' => 'Function execution schedule in CRON format.', 'default' => '', 'example' => '5 4 * * *', ]) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 7cb8adb815..b501e2119e 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1362,7 +1362,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $tooWide['headers']['status-code']); - $this->assertEquals('Attribute limit exceeded', $tooWide['body']['message']); + $this->assertEquals('attribute_limit_exceeded', $tooWide['body']['type']); } public function testIndexLimitException() From 6e6899c1e94cf6782ed8739f60f60c3c13b0ee6c Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 15 Nov 2024 13:14:14 +0100 Subject: [PATCH 044/340] Merge pull request #8988 from appwrite/fix-deletes Fix project type delete checks --- .github/workflows/tests.yml | 23 +++- src/Appwrite/Platform/Workers/Deletes.php | 25 ++--- .../Projects/ProjectsConsoleClientTest.php | 101 +++++++++++++++++- 3 files changed, 127 insertions(+), 22 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 29b3bdd70d..3ab240c1b9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -151,10 +151,25 @@ jobs: sleep 30 - name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode - run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug - env: - _APP_DATABASE_SHARED_TABLES: ${{ matrix.table_mode == 'Shared V1' || matrix.table_mode == 'Shared V2' && 'database_db_main' || '' }} - _APP_DATABASE_SHARED_TABLES_V1: ${{ matrix.table_mode == 'Shared V1' && 'database_db_main' || '' }} + run: | + if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then + echo "Using shared tables V1" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1=database_db_main + elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then + echo "Using shared tables V2" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1= + else + echo "Using project tables" + export _APP_DATABASE_SHARED_TABLES= + export _APP_DATABASE_SHARED_TABLES_V1= + fi + + docker compose exec -T \ + -e _APP_DATABASE_SHARED_TABLES \ + -e _APP_DATABASE_SHARED_TABLES_V1 \ + appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug benchmarking: name: Benchmark diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 700a480065..ddab8d0cf8 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -500,21 +500,14 @@ class Deletes extends Action $collections = $dbForProject->listCollections($limit); foreach ($collections as $collection) { - if (\in_array($dsn->getHost(), $sharedTables) || !\in_array($collection->getId(), $projectCollectionIds)) { - try { + try { + if (!\in_array($dsn->getHost(), $sharedTables) || !\in_array($collection->getId(), $projectCollectionIds)) { $dbForProject->deleteCollection($collection->getId()); - } catch (Throwable $e) { - Console::error('Error deleting '.$collection->getId().' '.$e->getMessage()); - - /** - * Ignore junction tables; - */ - if (!preg_match('/^_\d+_\d+$/', $collection->getId())) { - throw $e; - } + } else { + $this->deleteByGroup($collection->getId(), [], database: $dbForProject); } - } else { - $this->deleteByGroup($collection->getId(), [], database: $dbForProject); + } catch (Throwable $e) { + Console::error('Error deleting '.$collection->getId().' '.$e->getMessage()); } } @@ -572,10 +565,10 @@ class Deletes extends Action ], $dbForConsole); // Delete metadata table - if (\in_array($dsn->getHost(), $sharedTables)) { - $dbForProject->deleteCollection('_metadata'); + if (!\in_array($dsn->getHost(), $sharedTables)) { + $dbForProject->deleteCollection(Database::METADATA); } else { - $this->deleteByGroup('_metadata', [], $dbForProject); + $this->deleteByGroup(Database::METADATA, [], $dbForProject); } // Delete all storage directories diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 7b0847126c..e3f48bb2a6 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3727,11 +3727,11 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Amating Team', + 'name' => 'Amazing Team', ]); $this->assertEquals(201, $team['headers']['status-code']); - $this->assertEquals('Amating Team', $team['body']['name']); + $this->assertEquals('Amazing Team', $team['body']['name']); $this->assertNotEmpty($team['body']['$id']); $teamId = $team['body']['$id']; @@ -3794,6 +3794,103 @@ class ProjectsConsoleClientTest extends Scope return $data; } + public function testDeleteSharedProject(): void + { + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Amazing Team', + ]); + + $teamId = $team['body']['$id']; + + // Ensure deleting one project does not affect another project + $project1 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project 1', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + $project2 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project 2', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + $project1Id = $project1['body']['$id']; + $project2Id = $project2['body']['$id']; + + // Create user in each project + $key1 = $this->client->call(Client::METHOD_POST, '/projects/' . $project1Id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['users.read', 'users.write'], + ]); + + $user1 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1Id, + 'x-appwrite-key' => $key1['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test1@appwrite.io', + 'password' => 'password', + ]); + + $this->assertEquals(201, $user1['headers']['status-code']); + + $key2 = $this->client->call(Client::METHOD_POST, '/projects/' . $project2Id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['users.read', 'users.write'], + ]); + + $user2 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test2@appwrite.io', + 'password' => 'password', + ]); + + $this->assertEquals(201, $user2['headers']['status-code']); + + // Delete project 1 + $project1 = $this->client->call(Client::METHOD_DELETE, '/projects/' . $project1Id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $project1['headers']['status-code']); + + \sleep(3); + + // Ensure project 2 user is still there + $user2 = $this->client->call(Client::METHOD_GET, '/users/' . $user2['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ]); + + $this->assertEquals(200, $user2['headers']['status-code']); + } + /** * @depends testCreateProject */ From 908adebf74f94f0500c0c04cc92ab1630d5a8058 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 12 Nov 2024 17:51:57 +0100 Subject: [PATCH 045/340] Merge pull request #8964 from appwrite/debug-whitelist-console debug: whitelist console --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 663242882a..564a5b7df4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -63,7 +63,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo } if (System::getEnv('_APP_OPTIONS_ROUTER_PROTECTION', 'disabled') === 'enabled') { - if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) { // localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations + if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL && $host !== System::getEnv('_APP_CONSOLE_DOMAIN', '')) { throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.'); } } From f6e7c12b0294dea534759a1cfb54ca2bbabc220c Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:35:39 -0800 Subject: [PATCH 046/340] Merge pull request #8922 from appwrite/lohanidamodar-patch-4 Improve compression param checks --- app/controllers/api/storage.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index dda39a0db0..911481a1c0 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -68,19 +68,19 @@ App::post('/v1/storage/buckets') ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); - + $compression ??= Compression::NONE; try { $files = (Config::getParam('collections', [])['buckets'] ?? [])['files'] ?? []; if (empty($files)) { @@ -254,13 +254,13 @@ App::put('/v1/storage/buckets/:bucketId') ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -273,6 +273,7 @@ App::put('/v1/storage/buckets/:bucketId') $enabled ??= $bucket->getAttribute('enabled', true); $encryption ??= $bucket->getAttribute('encryption', true); $antivirus ??= $bucket->getAttribute('antivirus', true); + $compression ??= $bucket->getAttribute('compression', Compression::NONE); // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); From d257fdb0452ff4baf517394a299bef03bf03cfa2 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 8 Nov 2024 20:24:55 +0100 Subject: [PATCH 047/340] chore: remove redundant compression --- app/http.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/http.php b/app/http.php index 41f6283156..00c8eff21f 100644 --- a/app/http.php +++ b/app/http.php @@ -61,8 +61,6 @@ include __DIR__ . '/controllers/general.php'; $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) { $app = new App('UTC'); - $app->setCompression(true); - $app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB go(function () use ($register, $app) { $pools = $register->get('pools'); From 415dedc13598a5a787544d9643bc36b60943366b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 21 Nov 2024 16:46:10 +1300 Subject: [PATCH 048/340] Create V2 shared tables databases on server start --- app/http.php | 105 +++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/app/http.php b/app/http.php index 00c8eff21f..c821d7513c 100644 --- a/app/http.php +++ b/app/http.php @@ -12,6 +12,8 @@ use Swoole\Process; use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; +use Utopia\Cache\Adapter\None; +use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; @@ -90,7 +92,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg Console::success('[Setup] - Server database init started...'); try { - Console::success('[Setup] - Creating database: appwrite...'); + Console::success('[Setup] - Creating console database...'); $dbForConsole->create(); } catch (Duplicate) { Console::success('[Setup] - Skip: metadata table already exists'); @@ -117,34 +119,10 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg continue; } - Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); + Console::success('[Setup] - Creating console collection: ' . $collection['$id'] . '...'); - $attributes = []; - $indexes = []; - - foreach ($collection['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => ID::custom($attribute['$id']), - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } - - foreach ($collection['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => ID::custom($index['$id']), - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); - } + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); $dbForConsole->createCollection($key, $attributes, $indexes); } @@ -179,36 +157,55 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg throw new Exception('Files collection is not configured.'); } - $attributes = []; - $indexes = []; - - foreach ($files['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => ID::custom($attribute['$id']), - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } - - foreach ($files['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => ID::custom($index['$id']), - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); - } + $attributes = \array_map(fn ($attribute) => new Document($attribute), $files['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $files['indexes']); $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } + $projectCollections = $collections['projects']; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); + $sharedTablesV2 = \array_diff($sharedTables, $sharedTablesV1); + + $cache = $app->getResource('cache'); + + foreach ($sharedTablesV2 as $hostname) { + $adapter = $pools + ->get($hostname) + ->pop() + ->getResource(); + + $dbForProject = (new Database($adapter, $cache)) + ->setDatabase('appwrite') + ->setSharedTables(true) + ->setTenant(null) + ->setNamespace(System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + + try { + Console::success('[Setup] - Creating project database: ' . $hostname . '...'); + $dbForProject->create(); + } catch (Duplicate) { + Console::success('[Setup] - Skip: metadata table already exists'); + } + + foreach ($projectCollections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } + if (!$dbForProject->getCollection($key)->isEmpty()) { + continue; + } + + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); + + Console::success('[Setup] - Creating project collection: ' . $collection['$id'] . '...'); + + $dbForProject->createCollection($key, $attributes, $indexes); + } + } + $pools->reclaim(); Console::success('[Setup] - Server database init completed...'); From 018c865d04891d928d9867795be3846b14400ffa Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 21 Nov 2024 16:46:36 +1300 Subject: [PATCH 049/340] Skip all project db calls on project create if shared tables v2 --- app/controllers/api/projects.php | 132 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 65 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 39300a2d4a..92d3103293 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -205,81 +205,83 @@ App::post('/v1/projects') $sharedTablesV2 = !$projectTables && !$sharedTablesV1; $sharedTables = $sharedTablesV1 || $sharedTablesV2; - if ($sharedTables) { - $dbForProject - ->setSharedTables(true) - ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) - ->setNamespace($dsn->getParam('namespace')); - } else { - $dbForProject - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } + if (!$sharedTablesV2) { + if ($sharedTables) { + $dbForProject + ->setSharedTables(true) + ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) + ->setNamespace($dsn->getParam('namespace')); + } else { + $dbForProject + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } - $create = true; + $create = true; - try { - $dbForProject->create(); - } catch (Duplicate) { - $create = false; - } + try { + $dbForProject->create(); + } catch (Duplicate) { + $create = false; + } - if ($create || $projectTables) { - $audit = new Audit($dbForProject); - $audit->setup(); + if ($create || $projectTables) { + $audit = new Audit($dbForProject); + $audit->setup(); - $abuse = new TimeLimit('', 0, 1, $dbForProject); - $abuse->setup(); - } + $abuse = new TimeLimit('', 0, 1, $dbForProject); + $abuse->setup(); + } - if (!$create && $sharedTablesV1) { - $attributes = \array_map(fn ($attribute) => new Document($attribute), Audit::ATTRIBUTES); - $indexes = \array_map(fn (array $index) => new Document($index), Audit::INDEXES); - $dbForProject->createDocument(Database::METADATA, new Document([ - '$id' => ID::custom('audit'), - '$permissions' => [Permission::create(Role::any())], - 'name' => 'audit', - 'attributes' => $attributes, - 'indexes' => $indexes, - 'documentSecurity' => true - ])); + if (!$create && $sharedTablesV1) { + $attributes = \array_map(fn ($attribute) => new Document($attribute), Audit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), Audit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('audit'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'audit', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); - $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); - $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); - $dbForProject->createDocument(Database::METADATA, new Document([ - '$id' => ID::custom('abuse'), - '$permissions' => [Permission::create(Role::any())], - 'name' => 'abuse', - 'attributes' => $attributes, - 'indexes' => $indexes, - 'documentSecurity' => true - ])); - } + $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('abuse'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'abuse', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } - if ($create || $sharedTablesV1) { - /** @var array $collections */ - $collections = Config::getParam('collections', [])['projects'] ?? []; + if ($create || $sharedTablesV1) { + /** @var array $collections */ + $collections = Config::getParam('collections', [])['projects'] ?? []; - foreach ($collections as $key => $collection) { - if (($collection['$collection'] ?? '') !== Database::METADATA) { - continue; - } + foreach ($collections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } - $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); - $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); - try { - $dbForProject->createCollection($key, $attributes, $indexes); - } catch (Duplicate) { - $dbForProject->createDocument(Database::METADATA, new Document([ - '$id' => ID::custom($key), - '$permissions' => [Permission::create(Role::any())], - 'name' => $key, - 'attributes' => $attributes, - 'indexes' => $indexes, - 'documentSecurity' => true - ])); + try { + $dbForProject->createCollection($key, $attributes, $indexes); + } catch (Duplicate) { + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom($key), + '$permissions' => [Permission::create(Role::any())], + 'name' => $key, + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } } } } From 8410710005f0b12f70fa40ea263082d2d7e8be1b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 21 Nov 2024 16:47:12 +1300 Subject: [PATCH 050/340] Remove redundant DSN construction --- app/init.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/init.php b/app/init.php index 3744bb055c..047e9402b6 100644 --- a/app/init.php +++ b/app/init.php @@ -1425,13 +1425,6 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { From f9e518b2b099a45ed70bc0c45a5e2613f477a7f1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 21 Nov 2024 16:49:49 +1300 Subject: [PATCH 051/340] Fix shared tables v2 deletes --- app/http.php | 1 - docker-compose.yml | 2 ++ src/Appwrite/Platform/Workers/Deletes.php | 22 +++++++++++++++---- .../Projects/ProjectsConsoleClientTest.php | 12 ++++++++++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/http.php b/app/http.php index c821d7513c..4bfacd4cac 100644 --- a/app/http.php +++ b/app/http.php @@ -12,7 +12,6 @@ use Swoole\Process; use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; diff --git a/docker-compose.yml b/docker-compose.yml index 0f3f05847c..bae2cc7811 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -194,6 +194,7 @@ services: - _APP_EXPERIMENT_LOGGING_CONFIG - _APP_DATABASE_SHARED_TABLES - _APP_DATABASE_SHARED_TABLES_V1 + - _APP_DATABASE_SHARED_NAMESPACE appwrite-console: <<: *x-logging @@ -383,6 +384,7 @@ services: - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_DATABASE_SHARED_TABLES + - _APP_DATABASE_SHARED_TABLES_V1 appwrite-worker-databases: entrypoint: worker-databases diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index ddab8d0cf8..6c11116a4c 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -494,14 +494,21 @@ class Deletes extends Action ]; $limit = \count($projectCollectionIds) + 25; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); + + $projectTables = !\in_array($dsn->getHost(), $sharedTables); + $sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1); + $sharedTablesV2 = !$projectTables && !$sharedTablesV1; + $sharedTables = $sharedTablesV1 || $sharedTablesV2; while (true) { $collections = $dbForProject->listCollections($limit); foreach ($collections as $collection) { try { - if (!\in_array($dsn->getHost(), $sharedTables) || !\in_array($collection->getId(), $projectCollectionIds)) { + if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) { $dbForProject->deleteCollection($collection->getId()); } else { $this->deleteByGroup($collection->getId(), [], database: $dbForProject); @@ -511,7 +518,7 @@ class Deletes extends Action } } - if (\in_array($dsn->getHost(), $sharedTables)) { + if ($sharedTables) { $collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections); if (empty(\array_diff($collectionsIds, $projectCollectionIds))) { @@ -565,10 +572,17 @@ class Deletes extends Action ], $dbForConsole); // Delete metadata table - if (!\in_array($dsn->getHost(), $sharedTables)) { + if ($projectTables) { $dbForProject->deleteCollection(Database::METADATA); - } else { + } elseif ($sharedTablesV1) { $this->deleteByGroup(Database::METADATA, [], $dbForProject); + } elseif ($sharedTablesV2) { + $queries = \array_map( + fn ($id) => Query::notEqual('$id', $id), + $projectCollectionIds + ); + + $this->deleteByGroup(Database::METADATA, $queries, $dbForProject); } // Delete all storage directories diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index e3f48bb2a6..326443afcf 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3889,6 +3889,18 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(200, $user2['headers']['status-code']); + + // Create another user in project 2 in case read hits stale cache + $user3 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test3@appwrite.io' + ]); + + $this->assertEquals(201, $user3['headers']['status-code']); } /** From 2fcfd1d7c939777aa7e3be40309e3a504260b4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 22 Nov 2024 13:57:42 +0000 Subject: [PATCH 052/340] Add safe workers --- app/http.php | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) diff --git a/app/http.php b/app/http.php index 4bfacd4cac..c80fccee54 100644 --- a/app/http.php +++ b/app/http.php @@ -9,6 +9,7 @@ use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; use Swoole\Process; +use Swoole\Table; use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; @@ -16,11 +17,13 @@ use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; 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\Logger\Log; use Utopia\Logger\Log\User; @@ -28,6 +31,12 @@ use Utopia\Pools\Group; use Utopia\Swoole\Files; use Utopia\System\System; +const DOMAIN_SYNC_TIMER = 30; // 30 seconds + +$domains = new Table(1_000_000); // 1 million rows +$domains->column('value', Table::TYPE_INT, 1); +$domains->create(); + $http = new Server( host: "0.0.0.0", port: System::getEnv('PORT', 80), @@ -35,11 +44,12 @@ $http = new Server( ); $payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing -$workerNumber = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$totalWorkers = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); $http ->set([ - 'worker_num' => $workerNumber, + 'worker_num' => $totalWorkers, + 'dispatch_func' => 'dispatch', 'open_http2_protocol' => true, 'http_compression' => false, 'package_max_length' => $payloadSize, @@ -58,6 +68,93 @@ $http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) { Console::success('Reload completed...'); }); +/** + * Assigns HTTP requests to worker threads by analyzing its payload/content. + * + * Routes requests as 'safe' or 'risky' based on specific content patterns (like POST actions or certain domains) + * to optimize load distribution between the workers. Utilizes `$safeThreadsPercent` to manage risk by assigning + * riskier tasks to a dedicated worker subset. Prefers idle workers, with fallback to random selection if necessary. + * doc: https://openswoole.com/docs/modules/swoole-server/configuration#dispatch_func + * + * @param Server $server Swoole server instance. + * @param int $fd client ID + * @param int $type the type of data and its current state + * @param string|null $data Request content for categorization. + * @global int $totalThreads Total number of workers. + * @return int Chosen worker ID for the request. + */ +function dispatch(Server $server, int $fd, int $type, $data = null): int +{ + global $totalWorkers, $domains; + + // If data is not set we can send request to any worker + // first we try to pick idle worker, if not we randomly pick a worker + if ($data === null) { + for ($i = 0; $i < $totalWorkers; $i++) { + if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { + return $i; + } + } + return rand(0, $totalWorkers - 1); + } + + $riskyWorkersPercent = intval(System::getEnv('_APP_RISKY_WORKERS_PERCENT', 80)) / 100; // Decimal form 0 to 1 + + // Each worker has numeric ID, starting from 0 and incrementing + // From 0 to riskyWorkers, we consider safe workers + // From riskyWorkers to totalWorkers, we consider risky workers + $riskyWorkers = (int) floor($totalWorkers * $riskyWorkersPercent); // Absolute amount of risky workers + + $domain = ''; + // max up to 3 as first line has request details and second line has host + $lines = explode("\n", $data, 3); + $request = $lines[0]; + if (count($lines) > 1) { + $domain = trim(explode('Host: ', $lines[1])[1]); + } + + // Sync executions are considered risky + $risky = false; + if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) { + $risky = true; + } elseif (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) { + $risky = true; + } elseif ($domains->get(md5($domain), 'value') === 1) { + // executions request coming from custom domain + $risky = true; + } + + if ($risky) { + // If risky request, only consider risky workers + for ($j = $riskyWorkers; $j < $totalWorkers; $j++) { + /** Reference https://openswoole.com/docs/modules/swoole-server-getWorkerStatus#description */ + if ($server->getWorkerStatus($j) === SWOOLE_WORKER_IDLE) { + // If idle worker found, give to him + return $j; + } + } + + // If no idle workers, give to random risky worker + $worker = rand($riskyWorkers, $totalWorkers - 1); + Console::warning("swoole_dispatch: Risky branch: did not find a idle worker, picking random worker {$worker}"); + return $worker; + } + + // If safe request, give to any idle worker + // Its fine to pick risky worker here, because it's idle. Idle is never actually risky + for ($i = 0; $i < $totalWorkers; $i++) { + if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { + return $i; + } + } + + // If no idle worker found, give to random safe worker + // We avoid risky workers here, as it could be in work - not idle. Thats exactly when they are risky. + $worker = rand(0, $riskyWorkers - 1); + Console::warning("swoole_dispatch: Non-risky branch: did not find a idle worker, picking random worker {$worker}"); + return $worker; +} + include __DIR__ . '/controllers/general.php'; $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) { @@ -213,6 +310,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)'); Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}"); + // Start the task that starts fetching custom domains + $http->task([], 0); + // listen ctrl + c Process::signal(2, function () use ($http) { Console::log('Stop by Ctrl+C'); @@ -330,4 +430,59 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool } }); +// Fetch domains every `DOMAIN_SYNC_TIMER` seconds and update in the memory +$http->on('Task', function () use ($register, $domains) { + $lastSyncUpdate = null; + $pools = $register->get('pools'); + App::setResource('pools', fn () => $pools); + $app = new App('UTC'); + + /** @var Utopia\Database\Database $dbForConsole */ + $dbForConsole = $app->getResource('dbForConsole'); + + Console::loop(function () use ($dbForConsole, $domains, &$lastSyncUpdate) { + try { + $time = DateTime::now(); + $limit = 1000; + $sum = $limit; + $latestDocument = null; + + while ($sum === $limit) { + $queries = [Query::limit($limit)]; + if ($latestDocument !== null) { + $queries[] = Query::cursorAfter($latestDocument); + } + if ($lastSyncUpdate != null) { + $queries[] = Query::greaterThanEqual('$updatedAt', $lastSyncUpdate); + } + $queries[] = Query::equal('resourceType', ['function']); + $results = []; + try { + $results = Authorization::skip(fn () => $dbForConsole->find('rules', $queries)); + } catch (Throwable $th) { + Console::error($th->getMessage()); + } + + $sum = count($results); + foreach ($results as $document) { + $domain = $document->getAttribute('domain'); + if (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) { + continue; + } + $domains->set(md5($domain), ['value' => 1]); + } + $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + } + $lastSyncUpdate = $time; + if ($sum > 0) { + Console::log("Sync domains tick: {$sum} domains were updated"); + } + } catch (Throwable $th) { + Console::error($th->getMessage()); + } + }, DOMAIN_SYNC_TIMER, 0, function ($error) { + Console::error($error); + }); +}); + $http->start(); From 33dd4df6945cc0003bf534e3bb262351189e125e Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 22 Nov 2024 17:16:51 +0000 Subject: [PATCH 053/340] chore: backwards compatibility for 1.6.x --- app/controllers/api/functions.php | 3 +- app/controllers/api/proxy.php | 17 ++++++++-- app/controllers/general.php | 32 ++++++++++++++++--- .../Platform/Workers/Certificates.php | 10 ++++-- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 2309defe5a..5dc67677ac 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -328,7 +328,8 @@ App::post('/v1/functions') if (!empty($functionsDomain)) { $routeSubdomain = ID::unique(); $domain = "{$routeSubdomain}.{$functionsDomain}"; - $ruleId = md5($domain); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain); $rule = Authorization::skip( fn () => $dbForConsole->createDocument('rules', new Document([ diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 56fd31e88c..e015876935 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -11,6 +11,7 @@ use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; @@ -59,8 +60,16 @@ App::post('/v1/proxy/rules') throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); } - $ruleId = md5($domain); - $document = $dbForConsole->getDocument('rules', $ruleId); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + $document = $dbForConsole->findOne('rules', [ + Query::equal('domain', [$domain]), + ]); + } else { + $ruleId = md5($domain); + $document = $dbForConsole->getDocument('rules', $ruleId); + } + if (!$document->isEmpty()) { if ($document->getAttribute('projectId') === $project->getId()) { @@ -101,7 +110,9 @@ App::post('/v1/proxy/rules') throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $ruleId = md5($domain->get()); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain->get()); + $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/app/controllers/general.php b/app/controllers/general.php index 564a5b7df4..4c4761bba9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -29,6 +29,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Domains\Domain; use Utopia\DSN\DSN; @@ -51,7 +52,17 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $host = $request->getHostname() ?? ''; - $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + $route = Authorization::skip( + fn () => $dbForConsole->find('rules', [ + Query::equal('domain', [$host]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } else { + $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); + } if ($route->isEmpty()) { if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) { @@ -512,18 +523,31 @@ App::init() if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; } else { - $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + $domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]); + } else { + $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); + } $mainDomain = !$domainDocument->isEmpty() ? $domainDocument->getAttribute('domain') : $domain->get(); } if ($mainDomain !== $domain->get()) { Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { - $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + $domainDocument = $dbForConsole->findOne('rules', [ + Query::equal('domain', [$domain->get()]) + ]); + } else { + $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); + } if ($domainDocument->isEmpty()) { $domainDocument = new Document([ - '$id' => md5($domain->get()), + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + '$id' => version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain->get()), 'domain' => $domain->get(), 'resourceType' => 'api', 'status' => 'verifying', diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 21d967d9e1..6f1a710bc0 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -477,8 +477,14 @@ class Certificates extends Action */ private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void { - - $rule = $dbForConsole->getDocument('rules', md5($domain)); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + $rule = $dbForConsole->findOne('rules', [ + Query::equal('domain', [$domain]), + ]); + } else { + $rule = $dbForConsole->getDocument('rules', md5($domain)); + } if (!$rule->isEmpty()) { $rule->setAttribute('certificateId', $certificateId); From ae7cb3624007349ca1600328f75c0f9d74a6a18a Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 22 Nov 2024 17:18:23 +0000 Subject: [PATCH 054/340] chore: linter --- app/controllers/api/proxy.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index e015876935..029bc5e8b3 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -69,7 +69,7 @@ App::post('/v1/proxy/rules') $ruleId = md5($domain); $document = $dbForConsole->getDocument('rules', $ruleId); } - + if (!$document->isEmpty()) { if ($document->getAttribute('projectId') === $project->getId()) { @@ -112,7 +112,7 @@ App::post('/v1/proxy/rules') // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain->get()); - + $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), From 014c613c939543388cddd35946bbba510a79115b Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Fri, 22 Nov 2024 21:52:27 +0000 Subject: [PATCH 055/340] fix: update secret returned from users.createSession() 1. Include at least 1 factor because the minumum number of factors required when mfa is disabled is 1. 2. Purge the cached user document to ensure the new session is included in subsequent requests for the user. 3. Fix the encoding of the secret to match other parts of the codebase. --- app/controllers/api/users.php | 6 +++++- tests/e2e/Services/Users/UsersBase.php | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 42f7a59f54..bdb24572eb 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1804,6 +1804,7 @@ App::post('/v1/users/:userId/sessions') 'provider' => Auth::SESSION_PROVIDER_SERVER, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), + 'factors' => ['server'], 'ip' => $request->getIP(), 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', 'expire' => $expire, @@ -1816,8 +1817,11 @@ App::post('/v1/users/:userId/sessions') $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session = $dbForProject->createDocument('sessions', $session); + + $dbForProject->purgeCachedDocument('users', $user->getId()); + $session - ->setAttribute('secret', $secret) + ->setAttribute('secret', Auth::encodeSession($user->getId(), $secret)) ->setAttribute('countryName', $countryName); $queueForEvents diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index bd0a8ef937..bbf9a5e2df 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -310,6 +310,14 @@ trait UsersBase $this->assertNotEmpty($session['secret']); $this->assertNotEmpty($session['expire']); $this->assertEquals('server', $session['provider']); + + $response = $this->client->call(Client::METHOD_GET, '/account', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-session' => $session['secret'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); } From 98d78163a2b8de2c0ccf90ef5131fd28945bc526 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Fri, 22 Nov 2024 22:39:24 +0000 Subject: [PATCH 056/340] Bump console to version 5.2.25 --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 8d7fecb479..361685d1ed 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -167,7 +167,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:5.0.12 + image: /console:5.2.25 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index bae2cc7811..36a642f8f6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -199,7 +199,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.12 + image: appwrite/console:5.2.25 restart: unless-stopped networks: - appwrite From 07b3cbaec9de9ae586b224a0de2ce401027d8dcf Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Fri, 22 Nov 2024 22:47:02 +0000 Subject: [PATCH 057/340] Bump appwrite version to 1.6.1 --- README-CN.md | 6 +++--- README.md | 6 +++--- app/init.php | 2 +- src/Appwrite/Migration/Migration.php | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README-CN.md b/README-CN.md index a5eac1be03..92a9bf9806 100644 --- a/README-CN.md +++ b/README-CN.md @@ -67,7 +67,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` ### Windows @@ -79,7 +79,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` #### PowerShell @@ -89,7 +89,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index a9856a7310..ab57e65c4c 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` ### Windows @@ -87,7 +87,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` #### PowerShell @@ -97,7 +97,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.6.0 + appwrite/appwrite:1.6.1 ``` Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation. diff --git a/app/init.php b/app/init.php index 047e9402b6..d629f1a0b3 100644 --- a/app/init.php +++ b/app/init.php @@ -123,7 +123,7 @@ const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4318; -const APP_VERSION_STABLE = '1.6.0'; +const APP_VERSION_STABLE = '1.6.1'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index cee1b2d263..19f69b1a4f 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -91,6 +91,7 @@ abstract class Migration '1.5.10' => 'V20', '1.5.11' => 'V20', '1.6.0' => 'V21', + '1.6.1' => 'V21', ]; /** From 9d3bc1f80ae985e295f9e7b0fa62fdd0e901d7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 25 Nov 2024 11:04:04 +0100 Subject: [PATCH 058/340] Fix swoole task warning --- app/http.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/http.php b/app/http.php index c80fccee54..7387b3a43b 100644 --- a/app/http.php +++ b/app/http.php @@ -54,6 +54,7 @@ $http 'http_compression' => false, 'package_max_length' => $payloadSize, 'buffer_output_size' => $payloadSize, + 'task_worker_num' => 1, // required for the task to fetch domains background ]); $http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) { From cb385674a52ea9978243a334dd2c677dc3aacfc1 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:58:22 +0000 Subject: [PATCH 059/340] Add 1.6.1 to CHANGES.md --- CHANGES.md | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9b6172eeab..62db3d525e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,117 @@ +# Version 1.6.1 + +## What's Changed + +### Notable changes + +* Remove JPEG fallback for webp by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8746 +* Add heic and avif support by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7718 +* Add new runtimes by @Meldiron in https://github.com/appwrite/appwrite/pull/8771 +* Remove audits deletion by @shimonewman in https://github.com/appwrite/appwrite/pull/8766 +* Bump assistant by @loks0n in https://github.com/appwrite/appwrite/pull/8801 +* Change max queries values to 500 by @fogelito in https://github.com/appwrite/appwrite/pull/8802 +* Allow '.wav' as 'audio/x-wav' as well by @basert in https://github.com/appwrite/appwrite/pull/8846 +* Use 1 instead of 0.5 cpu for default function specification by @loks0n in https://github.com/appwrite/appwrite/pull/8848 +* Update function runtimes by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8781 +* Add a realtime heartbeat by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8943 + +### Fixes + +* Trigger functions event only if event is not paused by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8526 +* Update docker-compose to restart usage-dump by @feschaffa in https://github.com/appwrite/appwrite/pull/8642 +* Fix typo in scheduler base by @fogelito in https://github.com/appwrite/appwrite/pull/8691 +* Add domain and force HTTPS env vars to mail worker by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8722 +* Fix webp by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8732 +* Ignore junction tables by @fogelito in https://github.com/appwrite/appwrite/pull/8728 +* Fix logger throwing fatal error by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8724 +* Fix missing protocol for testing SMTP by @byawitz in https://github.com/appwrite/appwrite/pull/8749 +* Make create execution async loose by @loks0n in https://github.com/appwrite/appwrite/pull/8707 +* Fix invalid cursor value by @fogelito in https://github.com/appwrite/appwrite/pull/8109 +* Fix target deletes by @abnegate in https://github.com/appwrite/appwrite/pull/8833 +* Fix translation commas by @loks0n in https://github.com/appwrite/appwrite/pull/8892 +* Fix Migrations having source creds being overwritten and add Migration tests by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8897 +* Fix validator usage for updating string size by @abnegate in https://github.com/appwrite/appwrite/pull/8890 +* Fix create user event not triggering by @loks0n in https://github.com/appwrite/appwrite/pull/8718 +* Improve error handling and logging in the database worker by @fogelito in https://github.com/appwrite/appwrite/pull/8944 +* Remove inaccurate info about leaving the URL parameter empty by @ebenezerdon in https://github.com/appwrite/appwrite/pull/8963 +* Ensure indexes are updated when updating an attribute key by @fogelito in https://github.com/appwrite/appwrite/pull/8971 +* Remove duplicate dart-2.16 runtime template by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8972 +* Fix team invites with existing session by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/9006 +* Improve handling of HTTP requests by dispatching to safe workers by @Meldiron in https://github.com/appwrite/appwrite/pull/9016 +* Fix users create session secret by @stnguyen90 in https://github.com/appwrite/appwrite/pull/9019 +* Fix swoole task warning by @Meldiron in https://github.com/appwrite/appwrite/pull/9025 + +### Miscellaneous + +* Update Init copy by @adityaoberai in https://github.com/appwrite/appwrite/pull/8557 +* Fix security scan permissions and comment by @EVDOG4LIFE in https://github.com/appwrite/appwrite/pull/8525 +* Add Trivy security scans by @btme0011 in https://github.com/appwrite/appwrite/pull/6876 +* Update database stack by @abnegate in https://github.com/appwrite/appwrite/pull/8564 +* Bump database by @abnegate in https://github.com/appwrite/appwrite/pull/8573 +* Sync main with 1.5.x by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8589 +* Add AWS to one-click installs by @byawitz in https://github.com/appwrite/appwrite/pull/8593 +* Update Init copy in readme by @adityaoberai in https://github.com/appwrite/appwrite/pull/8618 +* Sync main into 1.6.x by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8685 +* Sync 1.6.x into main by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8686 +* Feat coroutines by @Meldiron in https://github.com/appwrite/appwrite/pull/7826 +* Sync main into 1.6.x by @Meldiron in https://github.com/appwrite/appwrite/pull/8719 +* Sentence casing endpoint API reference by @choir241 in https://github.com/appwrite/appwrite/pull/8617 +* DB storage metrics by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8404 +* Fix exception thrown when optional array attribute does not exist by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8391 +* Add projects channels to realtime by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8735 +* Base for console roles support by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8565 +* Remove DB disk storage calculation by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8745 +* Messaging adapter default values by @shimonewman in https://github.com/appwrite/appwrite/pull/8742 +* Add payload response type by @loks0n in https://github.com/appwrite/appwrite/pull/8720 +* Fix flaky functions tests by @loks0n in https://github.com/appwrite/appwrite/pull/8682 +* Migrations Backups by @fogelito in https://github.com/appwrite/appwrite/pull/8186 +* Add test for response and request filters by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8697 +* Bump version in SECURITY.md by @EVDOG4LIFE in https://github.com/appwrite/appwrite/pull/8755 +* Add originalId attribute to databases collection by @fogelito in https://github.com/appwrite/appwrite/pull/8764 +* Fix Walter References by @ItzNotABug in https://github.com/appwrite/appwrite/pull/8757 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8769 +* Move new attributes by @abnegate in https://github.com/appwrite/appwrite/pull/8777 +* Add ping endpoint by @loks0n in https://github.com/appwrite/appwrite/pull/8761 +* Fix GitHub action caching by @loks0n in https://github.com/appwrite/appwrite/pull/8772 +* Chore release ruby SDK by @abnegate in https://github.com/appwrite/appwrite/pull/8767 +* Call migration success on success by @abnegate in https://github.com/appwrite/appwrite/pull/8782 +* Update utopia-php/system to 0.9.0 by @basert in https://github.com/appwrite/appwrite/pull/8780 +* Move createDocument from api to worker by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8776 +* Add missing indexes by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8803 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8809 +* Fix typo in BLR region by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8756 +* Add tests for project variables by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8815 +* Replace 'Expires' with 'Cache-Control: private' header to avoid CDN caching by @basert in https://github.com/appwrite/appwrite/pull/8836 +* Allow blocking based on resource attributes by @basert in https://github.com/appwrite/appwrite/pull/8812 +* Check if resource is blocked inside functions worker by @basert in https://github.com/appwrite/appwrite/pull/8855 +* Fix missing allow attribute by @abnegate in https://github.com/appwrite/appwrite/pull/8889 +* Revert function execution order by @basert in https://github.com/appwrite/appwrite/pull/8857 +* Use resource type constants by @basert in https://github.com/appwrite/appwrite/pull/8895 +* Update Database lib by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8680 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8917 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8923 +* Update database for transaction counter fixes with retries by @abnegate in https://github.com/appwrite/appwrite/pull/8927 +* Validate string permissions by @fogelito in https://github.com/appwrite/appwrite/pull/8929 +* Add PubSub adapter support by @basert in https://github.com/appwrite/appwrite/pull/8905 +* List memberships as client by @loks0n in https://github.com/appwrite/appwrite/pull/8913 +* Fix XDebug Extension not being removed by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8891 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8946 +* Use utopia compression by @loks0n in https://github.com/appwrite/appwrite/pull/8938 +* Make compression minimum size configurable by @loks0n in https://github.com/appwrite/appwrite/pull/8947 +* Revert "Update database" by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8949 +* Fix setpaused by @loks0n in https://github.com/appwrite/appwrite/pull/8948 +* Use getDocument instead of find() for rules by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8951 +* Remove double fetch from migrations worker by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8956 +* Fix memberships privacy MFA by @loks0n in https://github.com/appwrite/appwrite/pull/8969 +* Add telemetry by @basert in https://github.com/appwrite/appwrite/pull/8960 +* Send migration errors individually by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8959 +* Add console sdk previews by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8990 +* Unset index length by @fogelito in https://github.com/appwrite/appwrite/pull/8978 +* Update base to 0.9.5 by @basert in https://github.com/appwrite/appwrite/pull/9005 +* Sync main into 1.6.x by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/9011 +* Improved shared tables V2 by @abnegate in https://github.com/appwrite/appwrite/pull/9013 +* Ensure backwards compatibility for 1.6.x by @christyjacob4 in https://github.com/appwrite/appwrite/pull/9018 + # Version 1.6.0 ## What's Changed From 580a9f331fc07b31ae2c5a068f5d6fc370334afb Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 26 Nov 2024 08:59:03 +0000 Subject: [PATCH 060/340] fix user update --- app/controllers/shared/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index a78bf1d88f..68c32cc969 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -316,7 +316,7 @@ App::init() /** * Update user last activity */ - if (!$user->isEmpty()) { + if (!empty($user->getId())) { $accessedAt = $user->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { $user->setAttribute('accessedAt', DateTime::now()); From 3a9ba8a6ad6a76454bc9dad586373cd949fd037a Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Tue, 22 Oct 2024 13:57:25 +0200 Subject: [PATCH 061/340] feat: move certificate generation to Adapter --- app/init.php | 15 ++ src/Appwrite/Certificates/Adapter.php | 14 ++ .../Certificates/Adapter/LetsEncrypt.php | 126 +++++++++++ src/Appwrite/Certificates/AdapterProvider.php | 19 ++ src/Appwrite/Platform/Tasks/Maintenance.php | 1 + .../Platform/Workers/Certificates.php | 206 ++++-------------- src/Appwrite/Platform/Workers/Deletes.php | 49 ++--- 7 files changed, 234 insertions(+), 196 deletions(-) create mode 100644 src/Appwrite/Certificates/Adapter.php create mode 100644 src/Appwrite/Certificates/Adapter/LetsEncrypt.php create mode 100644 src/Appwrite/Certificates/AdapterProvider.php diff --git a/app/init.php b/app/init.php index 047e9402b6..55f1356d62 100644 --- a/app/init.php +++ b/app/init.php @@ -21,6 +21,8 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { use Ahc\Jwt\JWT; use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; +use Appwrite\Certificates\Adapter\LetsEncrypt; +use Appwrite\Certificates\AdapterProvider; use Appwrite\Event\Audit; use Appwrite\Event\Build; use Appwrite\Event\Certificate; @@ -1531,6 +1533,19 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); +App::setResource('letsEncryptCertificateAdapter', function () { + $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); + if (empty($email)) { + throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue a LetsEncrypt SSL certificate.'); + } + + return new LetsEncrypt($email); +}); + +App::setResource('adapterForCertificates', function ($letsEncrypt) { + return new AdapterProvider(fn (string $domain) => $letsEncrypt); +}, ['letsEncryptCertificateAdapter']); + App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/src/Appwrite/Certificates/Adapter.php b/src/Appwrite/Certificates/Adapter.php new file mode 100644 index 0000000000..711e4c09b9 --- /dev/null +++ b/src/Appwrite/Certificates/Adapter.php @@ -0,0 +1,14 @@ +email = $email; + } + + + public function issueCertificate(string $certName, string $domain): ?string + { + $stdout = ''; + $stderr = ''; + + $staging = (App::isProduction()) ? '' : ' --dry-run'; + $exit = Console::execute( + "certbot certonly -v --webroot --noninteractive --agree-tos{$staging}" + . " --email " . $this->email + . " --cert-name " . $certName + . " -w " . APP_STORAGE_CERTIFICATES + . " -d {$domain}", + '', + $stdout, + $stderr + ); + + // Unexpected error, usually 5XX, API limits, ... + if ($exit !== 0) { + throw new Exception('Failed to issue a certificate with message: ' . $stderr); + } + + // Prepare folder in storage for domain + $path = APP_STORAGE_CERTIFICATES . '/' . $domain; + if (!\is_readable($path)) { + if (!\mkdir($path, 0755, true)) { + throw new Exception('Failed to create path for certificate.'); + } + } + + // Move generated files + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { + throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { + throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { + throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { + throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + $config = \implode(PHP_EOL, [ + "tls:", + " certificates:", + " - certFile: /storage/certificates/{$domain}/fullchain.pem", + " keyFile: /storage/certificates/{$domain}/privkey.pem" + ]); + + // Save configuration into Traefik using our new cert files + if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { + throw new Exception('Failed to save Traefik configuration.'); + } + + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + $certData = openssl_x509_parse(file_get_contents($certPath)); + $validTo = $certData['validTo_time_t'] ?? null; + $dt = (new \DateTime())->setTimestamp($validTo); + return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); + } + + public function isRenewRequired(string $domain, Log $log): bool + { + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + if (\file_exists($certPath)) { + $certData = openssl_x509_parse(file_get_contents($certPath)); + $validTo = $certData['validTo_time_t'] ?? 0; + + if (empty($validTo)) { + $log->addTag('certificateDomain', $domain); + throw new Exception('Unable to read certificate file (cert.pem).'); + } + + // LetsEncrypt allows renewal 30 days before expiry + $expiryInAdvance = (60 * 60 * 24 * 30); + if ($validTo - $expiryInAdvance > \time()) { + $log->addTag('certificateDomain', $domain); + $log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); + return false; + } + } + + return true; + } + + public function deleteCertificate(string $domain): void + { + $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; + $checkTraversal = realpath($directory) === $directory; + + if ($checkTraversal && is_dir($directory)) { + // Delete files, so Traefik is aware of change + array_map('unlink', glob($directory . '/*.*')); + rmdir($directory); + Console::info("Deleted certificate files for {$domain}"); + } else { + Console::info("No certificate files found for {$domain}"); + } + } +} diff --git a/src/Appwrite/Certificates/AdapterProvider.php b/src/Appwrite/Certificates/AdapterProvider.php new file mode 100644 index 0000000000..bed73a0164 --- /dev/null +++ b/src/Appwrite/Certificates/AdapterProvider.php @@ -0,0 +1,19 @@ +decisionMaker = $decisionMaker; + } + + public function get(string $domain): Adapter + { + return call_user_func($this->decisionMaker, $domain); + } + +} diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index afb38f35fc..40e72dc683 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -149,6 +149,7 @@ class Maintenance extends Action $certificates = $dbForConsole->find('certificates', [ Query::lessThan('attempts', 5), // Maximum 5 attempts + Query::isNotNull('renewDate'), Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) ]); diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 6f1a710bc0..ecb4cbd127 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Workers; +use Appwrite\Certificates\AdapterProvider; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Mail; @@ -11,7 +12,6 @@ use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model\Rule; use Exception; use Throwable; -use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -48,7 +48,11 @@ class Certificates extends Action ->inject('queueForEvents') ->inject('queueForFunctions') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log) => $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log)); + ->inject('adapterForCertificates') + ->callback( + fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates) => + $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $adapterForCertificates) + ); } /** @@ -58,11 +62,12 @@ class Certificates extends Action * @param Event $queueForEvents * @param Func $queueForFunctions * @param Log $log + * @param AdapterProvider $adapterForCertificates Retrieve the certificate adapter for the domain * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log): void + public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates): void { $payload = $message->getPayload() ?? []; @@ -76,7 +81,7 @@ class Certificates extends Action $log->addTag('domain', $domain->get()); - $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $skipRenewCheck); + $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $adapterForCertificates, $skipRenewCheck); } /** @@ -85,24 +90,24 @@ class Certificates extends Action * @param Mail $queueForMails * @param Event $queueForEvents * @param Func $queueForFunctions + * @param AdapterProvider $adapterForCertificates Retrieve the certificate adapter for the domain * @param bool $skipRenewCheck * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, bool $skipRenewCheck = false): void + private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates, bool $skipRenewCheck = false): void { /** * 1. Read arguments and validate domain * 2. Get main domain * 3. Validate CNAME DNS if parameter is not main domain (meaning it's custom domain) - * 4. Validate security email. Cannot be empty, required by LetsEncrypt - * 5. Validate renew date with certificate file, unless requested to skip by parameter - * 6. Issue a certificate using certbot CLI - * 7. Update 'log' attribute on certificate document with Certbot message - * 8. Create storage folder for certificate, if not ready already - * 9. Move certificates from Certbot location to our Storage - * 10. Create/Update our Storage with new Traefik config with new certificate paths + * 4. Validate renew date with certificate file, unless requested to skip by parameter + * 5. Issue a certificate using certbot CLI + * 6. Update 'log' attribute on certificate document with Certbot message + * 7. Create storage folder for certificate, if not ready already + * 8. Move certificates from Certbot location to our Storage + * 9. Create/Update our Storage with new Traefik config with new certificate paths * 11. Read certificate file and update 'renewDate' on certificate document * 12. Update 'issueDate' and 'attempts' on certificate * @@ -119,7 +124,7 @@ class Certificates extends Action * 2. Save document to database * 3. Update all domains documents with current certificate ID * - * Note: Renewals are checked and scheduled from maintenence worker + * Note: Renewals are checked and scheduled from maintenance worker */ // Get current certificate @@ -131,43 +136,32 @@ class Certificates extends Action $certificate->setAttribute('domain', $domain->get()); } + $certificateAdapter = $adapterForCertificates->get($domain->get()); + $success = false; try { - // Email for alerts is required by LetsEncrypt - $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); - if (empty($email)) { - throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue an SSL certificate.'); - } - // Validate domain and DNS records. Skip if job is forced if (!$skipRenewCheck) { $mainDomain = $this->getMainDomain(); $isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain; $this->validateDomain($domain, $isMainDomain, $log); + + // If certificate exists already, double-check expiry date. Skip if job is forced + if (!$certificateAdapter->isRenewRequired($domain->get(), $log)) { + throw new Exception('Renew isn\'t required.'); + } } - // If certificate exists already, double-check expiry date. Skip if job is forced - if (!$skipRenewCheck && !$this->isRenewRequired($domain->get(), $log)) { - throw new Exception('Renew isn\'t required.'); - } - - // Prepare folder name for certbot. Using this helps prevent miss-match in LetsEncrypt configuration when renewing certificate - $folder = ID::unique(); - - // Generate certificate files using Let's Encrypt - $letsEncryptData = $this->issueCertificate($folder, $domain->get(), $email); + // Prepare unique cert name. Using this helps prevent miss-match in configuration when renewing certificates. + $certName = ID::unique(); + $renewDate = $certificateAdapter->issueCertificate($certName, $domain->get()); // Command succeeded, store all data into document - $logs = 'Certificate successfully generated.'; - $certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB - - - // Give certificates to Traefik - $this->applyCertificateFiles($folder, $domain->get(), $letsEncryptData); + $certificate->setAttribute('logs', 'Certificate successfully generated.'); // Update certificate info stored in database - $certificate->setAttribute('renewDate', $this->getRenewDate($domain->get())); + $certificate->setAttribute('renewDate', $renewDate); $certificate->setAttribute('attempts', 0); $certificate->setAttribute('issueDate', DateTime::now()); $success = true; @@ -181,7 +175,7 @@ class Certificates extends Action $attempts = $certificate->getAttribute('attempts', 0) + 1; $certificate->setAttribute('attempts', $attempts); - // Store cuttent time as renew date to ensure another attempt in next maintenance cycle + // Store current time as renew date to ensure another attempt in next maintenance cycle. $certificate->setAttribute('renewDate', DateTime::now()); // Send email to security email @@ -245,8 +239,8 @@ class Certificates extends Action } /** - * Internal domain validation functionality to prevent unnecessary attempts failed from Let's Encrypt side. We check: - * - Domain needs to be public and valid (prevents NFT domains that are not supported by Let's Encrypt) + * Internal domain validation functionality to prevent unnecessary attempts. We check: + * - Domain needs to be public and valid (prevents NFT domains that are not supported) * - Domain must have proper DNS record * * @param Domain $domain Domain which we validate @@ -292,136 +286,6 @@ class Certificates extends Action } } - /** - * Reads expiry date of certificate from file and decides if renewal is required or not. - * - * @param string $domain Domain for which we check certificate file - * @return bool True, if certificate needs to be renewed - * @throws Exception - */ - private function isRenewRequired(string $domain, Log $log): bool - { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; - if (\file_exists($certPath)) { - $validTo = null; - - $certData = openssl_x509_parse(file_get_contents($certPath)); - $validTo = $certData['validTo_time_t'] ?? 0; - - if (empty($validTo)) { - $log->addTag('certificateDomain', $domain); - throw new Exception('Unable to read certificate file (cert.pem).'); - } - - // LetsEncrypt allows renewal 30 days before expiry - $expiryInAdvance = (60 * 60 * 24 * 30); - if ($validTo - $expiryInAdvance > \time()) { - $log->addTag('certificateDomain', $domain); - $log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); - return false; - } - } - - return true; - } - - /** - * LetsEncrypt communication to issue certificate (using certbot CLI) - * - * @param string $folder Folder into which certificates should be generated - * @param string $domain Domain to generate certificate for - * @return array Named array with keys 'stdout' and 'stderr', both string - * @throws Exception - */ - private function issueCertificate(string $folder, string $domain, string $email): array - { - $stdout = ''; - $stderr = ''; - - $staging = (App::isProduction()) ? '' : ' --dry-run'; - $exit = Console::execute("certbot certonly -v --webroot --noninteractive --agree-tos{$staging}" - . " --email " . $email - . " --cert-name " . $folder - . " -w " . APP_STORAGE_CERTIFICATES - . " -d {$domain}", '', $stdout, $stderr); - - // Unexpected error, usually 5XX, API limits, ... - if ($exit !== 0) { - throw new Exception('Failed to issue a certificate with message: ' . $stderr); - } - - return [ - 'stdout' => $stdout, - 'stderr' => $stderr - ]; - } - - /** - * Read new renew date from certificate file generated by Let's Encrypt - * - * @param string $domain Domain which certificate was generated for - * @return string - * @throws \Utopia\Database\Exception - */ - private function getRenewDate(string $domain): string - { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; - $certData = openssl_x509_parse(file_get_contents($certPath)); - $validTo = $certData['validTo_time_t'] ?? null; - $dt = (new \DateTime())->setTimestamp($validTo); - return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); // -30 days - } - - /** - * Method to take files from Let's Encrypt, and put it into Traefik. - * - * @param string $domain Domain which certificate was generated for - * @param string $folder Folder in which certificates were generated - * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error - * @return void - * @throws Exception - */ - private function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void - { - - // Prepare folder in storage for domain - $path = APP_STORAGE_CERTIFICATES . '/' . $domain; - if (!\is_readable($path)) { - if (!\mkdir($path, 0755, true)) { - throw new Exception('Failed to create path for certificate.'); - } - } - - // Move generated files - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { - throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { - throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { - throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { - throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - $config = \implode(PHP_EOL, [ - "tls:", - " certificates:", - " - certFile: /storage/certificates/{$domain}/fullchain.pem", - " keyFile: /storage/certificates/{$domain}/privkey.pem" - ]); - - // Save configuration into Traefik using our new cert files - if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { - throw new Exception('Failed to save Traefik configuration.'); - } - } - /** * Method to make sure information about error is delivered to admnistrator. * @@ -500,6 +364,10 @@ class Certificates extends Action $project = $dbForConsole->getDocument('projects', $projectId); + if ($project->isEmpty()) { + return; + } + /** Trigger Webhook */ $ruleModel = new Rule(); $queueForEvents diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 6c11116a4c..b4570e3929 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Workers; use Appwrite\Auth\Auth; +use Appwrite\Certificates\AdapterProvider; use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; @@ -50,18 +51,22 @@ class Deletes extends Action ->inject('deviceForFunctions') ->inject('deviceForBuilds') ->inject('deviceForCache') + ->inject('adapterForCertificates') ->inject('abuseRetention') ->inject('executionRetention') ->inject('auditRetention') ->inject('log') - ->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log)); + ->callback( + fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $abuseRetention, $executionRetention, $auditRetention, $log) + ); } /** * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -84,10 +89,10 @@ class Deletes extends Action case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { case DELETE_TYPE_PROJECTS: - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $document); + $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $document); break; case DELETE_TYPE_FUNCTIONS: - $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); + $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $adapterProvider, $document, $project); break; case DELETE_TYPE_DEPLOYMENTS: $this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); @@ -102,7 +107,7 @@ class Deletes extends Action $this->deleteInstallation($dbForConsole, $getProjectDB, $document, $project); break; case DELETE_TYPE_RULES: - $this->deleteRule($dbForConsole, $document); + $this->deleteRule($dbForConsole, $document, $adapterProvider); break; default: Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); @@ -110,7 +115,7 @@ class Deletes extends Action } break; case DELETE_TYPE_TEAM_PROJECTS: - $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $document); + $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $adapterProvider, $document); break; case DELETE_TYPE_EXECUTIONS: $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); @@ -442,7 +447,7 @@ class Deletes extends Action * @throws Structure * @throws Exception */ - private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, Document $document): void + private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, AdapterProvider $adapterProvider, Document $document): void { $projects = $dbForConsole->find('projects', [ @@ -455,7 +460,7 @@ class Deletes extends Action $deviceForBuilds = getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); $deviceForCache = getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $project); + $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $project); $dbForConsole->deleteDocument('projects', $project->getId()); } } @@ -473,7 +478,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, Document $document): void + private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, Document $document): void { $projectInternalId = $document->getInternalId(); $projectId = $document->getId(); @@ -537,8 +542,8 @@ class Deletes extends Action // Delete project and function rules $this->deleteByGroup('rules', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole, function (Document $document) use ($dbForConsole) { - $this->deleteRule($dbForConsole, $document); + ], $dbForConsole, function (Document $document) use ($dbForConsole, $adapterProvider) { + $this->deleteRule($dbForConsole, $document, $adapterProvider); }); // Delete Keys @@ -746,7 +751,7 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void + private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, AdapterProvider $adapterProvider, Document $document, Document $project): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); @@ -761,8 +766,8 @@ class Deletes extends Action Query::equal('resourceType', ['function']), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('projectInternalId', [$project->getInternalId()]) - ], $dbForConsole, function (Document $document) use ($project, $dbForConsole) { - $this->deleteRule($dbForConsole, $document); + ], $dbForConsole, function (Document $document) use ($project, $dbForConsole, $adapterProvider) { + $this->deleteRule($dbForConsole, $document, $adapterProvider); }); /** @@ -1048,21 +1053,11 @@ class Deletes extends Action * @param Document $document rule document * @return void */ - private function deleteRule(Database $dbForConsole, Document $document): void + private function deleteRule(Database $dbForConsole, Document $document, AdapterProvider $adapterForCertificate): void { - $domain = $document->getAttribute('domain'); - $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; - $checkTraversal = realpath($directory) === $directory; - - if ($checkTraversal && is_dir($directory)) { - // Delete files, so Traefik is aware of change - array_map('unlink', glob($directory . '/*.*')); - rmdir($directory); - Console::info("Deleted certificate files for {$domain}"); - } else { - Console::info("No certificate files found for {$domain}"); - } + $adapter = $adapterForCertificate->get($domain); + $adapter->deleteCertificate($domain); // Delete certificate document, so Appwrite is aware of change if (isset($document['certificateId'])) { From 98984a808500264fb2b3ce14801a7fb062e33d39 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Wed, 20 Nov 2024 11:10:57 +0100 Subject: [PATCH 062/340] refactor: use single adapter --- app/init.php | 15 ------- app/worker.php | 11 ++++- docker-compose.yml | 1 + src/Appwrite/Certificates/AdapterProvider.php | 19 --------- .../{Adapter => }/LetsEncrypt.php | 3 +- .../Platform/Workers/Certificates.php | 24 +++++------ src/Appwrite/Platform/Workers/Deletes.php | 41 +++++++++---------- 7 files changed, 43 insertions(+), 71 deletions(-) delete mode 100644 src/Appwrite/Certificates/AdapterProvider.php rename src/Appwrite/Certificates/{Adapter => }/LetsEncrypt.php (98%) diff --git a/app/init.php b/app/init.php index 55f1356d62..047e9402b6 100644 --- a/app/init.php +++ b/app/init.php @@ -21,8 +21,6 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { use Ahc\Jwt\JWT; use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; -use Appwrite\Certificates\Adapter\LetsEncrypt; -use Appwrite\Certificates\AdapterProvider; use Appwrite\Event\Audit; use Appwrite\Event\Build; use Appwrite\Event\Certificate; @@ -1533,19 +1531,6 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); -App::setResource('letsEncryptCertificateAdapter', function () { - $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); - if (empty($email)) { - throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue a LetsEncrypt SSL certificate.'); - } - - return new LetsEncrypt($email); -}); - -App::setResource('adapterForCertificates', function ($letsEncrypt) { - return new AdapterProvider(fn (string $domain) => $letsEncrypt); -}, ['letsEncryptCertificateAdapter']); - App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/app/worker.php b/app/worker.php index 7899c1d5bc..280e170028 100644 --- a/app/worker.php +++ b/app/worker.php @@ -2,6 +2,7 @@ require_once __DIR__ . '/init.php'; +use Appwrite\Certificates\LetsEncrypt; use Appwrite\Event\Audit; use Appwrite\Event\Build; use Appwrite\Event\Certificate; @@ -16,7 +17,6 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; -use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -283,6 +283,15 @@ Server::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); +Server::setResource('certificates', function () { + $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); + if (empty($email)) { + throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue a LetsEncrypt SSL certificate.'); + } + + return new LetsEncrypt($email); +}); + Server::setResource('logError', function (Registry $register, Document $project) { return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) { $logger = $register->get('logger'); diff --git a/docker-compose.yml b/docker-compose.yml index 36a642f8f6..ef8d898250 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -385,6 +385,7 @@ services: - _APP_EXECUTOR_HOST - _APP_DATABASE_SHARED_TABLES - _APP_DATABASE_SHARED_TABLES_V1 + - _APP_EMAIL_CERTIFICATES appwrite-worker-databases: entrypoint: worker-databases diff --git a/src/Appwrite/Certificates/AdapterProvider.php b/src/Appwrite/Certificates/AdapterProvider.php deleted file mode 100644 index bed73a0164..0000000000 --- a/src/Appwrite/Certificates/AdapterProvider.php +++ /dev/null @@ -1,19 +0,0 @@ -decisionMaker = $decisionMaker; - } - - public function get(string $domain): Adapter - { - return call_user_func($this->decisionMaker, $domain); - } - -} diff --git a/src/Appwrite/Certificates/Adapter/LetsEncrypt.php b/src/Appwrite/Certificates/LetsEncrypt.php similarity index 98% rename from src/Appwrite/Certificates/Adapter/LetsEncrypt.php rename to src/Appwrite/Certificates/LetsEncrypt.php index b2237189e9..3896eab022 100644 --- a/src/Appwrite/Certificates/Adapter/LetsEncrypt.php +++ b/src/Appwrite/Certificates/LetsEncrypt.php @@ -1,8 +1,7 @@ inject('queueForEvents') ->inject('queueForFunctions') ->inject('log') - ->inject('adapterForCertificates') + ->inject('certificates') ->callback( - fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates) => - $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $adapterForCertificates) + fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates) => + $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates) ); } @@ -62,12 +62,12 @@ class Certificates extends Action * @param Event $queueForEvents * @param Func $queueForFunctions * @param Log $log - * @param AdapterProvider $adapterForCertificates Retrieve the certificate adapter for the domain + * @param CertificatesAdapter $certificates * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates): void + public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates): void { $payload = $message->getPayload() ?? []; @@ -81,7 +81,7 @@ class Certificates extends Action $log->addTag('domain', $domain->get()); - $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $adapterForCertificates, $skipRenewCheck); + $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates, $skipRenewCheck); } /** @@ -90,13 +90,13 @@ class Certificates extends Action * @param Mail $queueForMails * @param Event $queueForEvents * @param Func $queueForFunctions - * @param AdapterProvider $adapterForCertificates Retrieve the certificate adapter for the domain + * @param CertificatesAdapter $certificates * @param bool $skipRenewCheck * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, AdapterProvider $adapterForCertificates, bool $skipRenewCheck = false): void + private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates, bool $skipRenewCheck = false): void { /** * 1. Read arguments and validate domain @@ -136,8 +136,6 @@ class Certificates extends Action $certificate->setAttribute('domain', $domain->get()); } - $certificateAdapter = $adapterForCertificates->get($domain->get()); - $success = false; try { @@ -148,14 +146,14 @@ class Certificates extends Action $this->validateDomain($domain, $isMainDomain, $log); // If certificate exists already, double-check expiry date. Skip if job is forced - if (!$certificateAdapter->isRenewRequired($domain->get(), $log)) { + if (!$certificates->isRenewRequired($domain->get(), $log)) { throw new Exception('Renew isn\'t required.'); } } // Prepare unique cert name. Using this helps prevent miss-match in configuration when renewing certificates. $certName = ID::unique(); - $renewDate = $certificateAdapter->issueCertificate($certName, $domain->get()); + $renewDate = $certificates->issueCertificate($certName, $domain->get()); // Command succeeded, store all data into document $certificate->setAttribute('logs', 'Certificate successfully generated.'); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index b4570e3929..e6002bf75f 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Workers; use Appwrite\Auth\Auth; -use Appwrite\Certificates\AdapterProvider; +use Appwrite\Certificates\Adapter as CertificatesAdapter; use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; @@ -51,14 +51,14 @@ class Deletes extends Action ->inject('deviceForFunctions') ->inject('deviceForBuilds') ->inject('deviceForCache') - ->inject('adapterForCertificates') + ->inject('certificates') ->inject('abuseRetention') ->inject('executionRetention') ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -89,10 +89,10 @@ class Deletes extends Action case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { case DELETE_TYPE_PROJECTS: - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $document); + $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document); break; case DELETE_TYPE_FUNCTIONS: - $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $adapterProvider, $document, $project); + $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project); break; case DELETE_TYPE_DEPLOYMENTS: $this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); @@ -107,7 +107,7 @@ class Deletes extends Action $this->deleteInstallation($dbForConsole, $getProjectDB, $document, $project); break; case DELETE_TYPE_RULES: - $this->deleteRule($dbForConsole, $document, $adapterProvider); + $this->deleteRule($dbForConsole, $document, $certificates); break; default: Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); @@ -115,7 +115,7 @@ class Deletes extends Action } break; case DELETE_TYPE_TEAM_PROJECTS: - $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $adapterProvider, $document); + $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $certificates, $document); break; case DELETE_TYPE_EXECUTIONS: $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); @@ -269,7 +269,7 @@ class Deletes extends Action MESSAGE_TYPE_EMAIL => 'emailTotal', MESSAGE_TYPE_SMS => 'smsTotal', MESSAGE_TYPE_PUSH => 'pushTotal', - default => throw new Exception('Invalid target provider type'), + default => throw new Exception('Invalid target CertificatesAdapter type'), }; $dbForProject->decreaseDocumentAttribute( 'topics', @@ -447,7 +447,7 @@ class Deletes extends Action * @throws Structure * @throws Exception */ - private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, AdapterProvider $adapterProvider, Document $document): void + private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void { $projects = $dbForConsole->find('projects', [ @@ -460,7 +460,7 @@ class Deletes extends Action $deviceForBuilds = getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); $deviceForCache = getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $adapterProvider, $project); + $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $project); $dbForConsole->deleteDocument('projects', $project->getId()); } } @@ -478,7 +478,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, AdapterProvider $adapterProvider, Document $document): void + private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { $projectInternalId = $document->getInternalId(); $projectId = $document->getId(); @@ -542,8 +542,8 @@ class Deletes extends Action // Delete project and function rules $this->deleteByGroup('rules', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole, function (Document $document) use ($dbForConsole, $adapterProvider) { - $this->deleteRule($dbForConsole, $document, $adapterProvider); + ], $dbForConsole, function (Document $document) use ($dbForConsole, $certificates) { + $this->deleteRule($dbForConsole, $document, $certificates); }); // Delete Keys @@ -751,7 +751,7 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, AdapterProvider $adapterProvider, Document $document, Document $project): void + private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); @@ -766,8 +766,8 @@ class Deletes extends Action Query::equal('resourceType', ['function']), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('projectInternalId', [$project->getInternalId()]) - ], $dbForConsole, function (Document $document) use ($project, $dbForConsole, $adapterProvider) { - $this->deleteRule($dbForConsole, $document, $adapterProvider); + ], $dbForConsole, function (Document $document) use ($project, $dbForConsole, $certificates) { + $this->deleteRule($dbForConsole, $document, $certificates); }); /** @@ -1053,11 +1053,10 @@ class Deletes extends Action * @param Document $document rule document * @return void */ - private function deleteRule(Database $dbForConsole, Document $document, AdapterProvider $adapterForCertificate): void + private function deleteRule(Database $dbForConsole, Document $document, CertificatesAdapter $certificates): void { $domain = $document->getAttribute('domain'); - $adapter = $adapterForCertificate->get($domain); - $adapter->deleteCertificate($domain); + $certificates->deleteCertificate($domain); // Delete certificate document, so Appwrite is aware of change if (isset($document['certificateId'])) { From 442459f6a482121f573168458cafb767875467ec Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 26 Nov 2024 16:14:38 +0200 Subject: [PATCH 063/340] fix restoration --- composer.json | 2 +- composer.lock | 39 ++++++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index e3fbcabc83..5fb781083c 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.12.*", - "utopia-php/migration": "0.6.*", + "utopia-php/migration": "dev-0.6.x-fix-structore-validation as 0.6.13", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.5.*", diff --git a/composer.lock b/composer.lock index 87d8b47583..c742097e13 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": "ae3b9a491c9870a4897cdf712caba1e3", + "content-hash": "8e458c412c8a8ce3ce018b7a2c690832", "packages": [ { "name": "adhocore/jwt", @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.16.4", + "version": "0.16.5", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "7e4741337b9373f77210396e68eca539018cabd1" + "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/7e4741337b9373f77210396e68eca539018cabd1", - "reference": "7e4741337b9373f77210396e68eca539018cabd1", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", + "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", "shasum": "" }, "require": { @@ -206,9 +206,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.16.4" + "source": "https://github.com/appwrite/runtimes/tree/0.16.5" }, - "time": "2024-10-26T10:39:59+00:00" + "time": "2024-11-25T15:17:06+00:00" }, { "name": "beberlei/assert", @@ -3928,16 +3928,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.12", + "version": "dev-0.6.x-fix-structore-validation", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "9a8c905af4cece5c5ec9542a5b534befce067260" + "reference": "ed735136dd10a88ab8601a9831e9cbcf3b6d6560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/9a8c905af4cece5c5ec9542a5b534befce067260", - "reference": "9a8c905af4cece5c5ec9542a5b534befce067260", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ed735136dd10a88ab8601a9831e9cbcf3b6d6560", + "reference": "ed735136dd10a88ab8601a9831e9cbcf3b6d6560", "shasum": "" }, "require": { @@ -3978,9 +3978,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.12" + "source": "https://github.com/utopia-php/migration/tree/0.6.x-fix-structore-validation" }, - "time": "2024-11-12T00:31:53+00:00" + "time": "2024-11-26T11:04:12+00:00" }, { "name": "utopia-php/mongo", @@ -8555,9 +8555,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/migration", + "version": "dev-0.6.x-fix-structore-validation", + "alias": "0.6.13", + "alias_normalized": "0.6.13.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/migration": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From 135ff1a72400487c827033e3943a96dd322bea4e Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 26 Nov 2024 17:05:17 +0200 Subject: [PATCH 064/340] bomb migration 0.6.13 --- composer.json | 2 +- composer.lock | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index 5fb781083c..e3fbcabc83 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.12.*", - "utopia-php/migration": "dev-0.6.x-fix-structore-validation as 0.6.13", + "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.5.*", diff --git a/composer.lock b/composer.lock index c742097e13..bdb41c2478 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": "8e458c412c8a8ce3ce018b7a2c690832", + "content-hash": "ae3b9a491c9870a4897cdf712caba1e3", "packages": [ { "name": "adhocore/jwt", @@ -3928,16 +3928,16 @@ }, { "name": "utopia-php/migration", - "version": "dev-0.6.x-fix-structore-validation", + "version": "0.6.13", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "ed735136dd10a88ab8601a9831e9cbcf3b6d6560" + "reference": "68d9b0a9477755afcda607e7e8109785cae17a13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/ed735136dd10a88ab8601a9831e9cbcf3b6d6560", - "reference": "ed735136dd10a88ab8601a9831e9cbcf3b6d6560", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/68d9b0a9477755afcda607e7e8109785cae17a13", + "reference": "68d9b0a9477755afcda607e7e8109785cae17a13", "shasum": "" }, "require": { @@ -3978,9 +3978,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.x-fix-structore-validation" + "source": "https://github.com/utopia-php/migration/tree/0.6.13" }, - "time": "2024-11-26T11:04:12+00:00" + "time": "2024-11-26T13:57:53+00:00" }, { "name": "utopia-php/mongo", @@ -8555,18 +8555,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/migration", - "version": "dev-0.6.x-fix-structore-validation", - "alias": "0.6.13", - "alias_normalized": "0.6.13.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/migration": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From f0b6c729c925efc5148153ab2f3ad2d6b0d20a69 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Tue, 26 Nov 2024 14:54:27 +0100 Subject: [PATCH 065/340] feat: add more tags to sentry --- app/cli.php | 2 +- app/controllers/general.php | 5 ++++- app/http.php | 5 ++++- app/realtime.php | 2 +- app/worker.php | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/cli.php b/app/cli.php index b0f053d3c6..fd49d2fed4 100644 --- a/app/cli.php +++ b/app/cli.php @@ -181,7 +181,7 @@ CLI::setResource('logError', function (Registry $register) { $log = new Log(); $log->setNamespace($namespace); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); diff --git a/app/controllers/general.php b/app/controllers/general.php index 4c4761bba9..9e589452ec 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -861,6 +861,8 @@ App::error() if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); + } else { + $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); } try { @@ -871,7 +873,7 @@ App::error() } $log->setNamespace("http"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); @@ -892,6 +894,7 @@ App::error() $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); $log->setAction($action); + $log->addTag('service', $action); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/app/http.php b/app/http.php index 7387b3a43b..c4e48a7f69 100644 --- a/app/http.php +++ b/app/http.php @@ -370,10 +370,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); + } else { + $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); } $log->setNamespace("http"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($th->getMessage()); @@ -393,6 +395,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); $log->setAction($action); + $log->addTag('service', $action); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/app/realtime.php b/app/realtime.php index cfb9bf9a16..03eaa53bcc 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -184,7 +184,7 @@ $logError = function (Throwable $error, string $action) use ($register) { $log = new Log(); $log->setNamespace("realtime"); - $log->setServer(gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); diff --git a/app/worker.php b/app/worker.php index 280e170028..7e4eafeea2 100644 --- a/app/worker.php +++ b/app/worker.php @@ -301,7 +301,7 @@ Server::setResource('logError', function (Registry $register, Document $project) $log = new Log(); $log->setNamespace($namespace); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); @@ -394,7 +394,7 @@ $worker if ($logger) { $log->setNamespace("appwrite-worker"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); From ca6cd349fb6e033af13d69b76dd6d1568df70658 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 27 Nov 2024 14:35:58 +0200 Subject: [PATCH 066/340] Remove failed attribute --- src/Appwrite/Platform/Workers/Databases.php | 28 ++++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 763967bb56..b027b3e707 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -251,23 +251,21 @@ class Databases extends Action try { try { - if ($status !== 'failed') { - if ($type === Database::VAR_RELATIONSHIP) { - if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { - throw new DatabaseException('Collection not found'); - } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + if ($type === Database::VAR_RELATIONSHIP) { + if ($options['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new DatabaseException('Collection not found'); } - - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); - throw new DatabaseException('Failed to delete Relationship'); - } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - throw new DatabaseException('Failed to delete Attribute'); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } + + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); + throw new DatabaseException('Failed to delete Relationship'); + } + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + throw new DatabaseException('Failed to delete Attribute'); } $dbForProject->deleteDocument('attributes', $attribute->getId()); From 98864b04e133918553ce7525fc7d88ed5c086cce Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 27 Nov 2024 18:02:37 +0200 Subject: [PATCH 067/340] fix $options --- app/controllers/api/databases.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index a00324f3b7..aad072c50a 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -290,15 +290,9 @@ function updateAttribute( $attribute->setAttribute('size', $size); } - $formatOptions = $attribute->getAttribute('formatOptions'); - switch ($attribute->getAttribute('format')) { case APP_DATABASE_ATTRIBUTE_INT_RANGE: case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: - if ($min === $formatOptions['min'] && $max === $formatOptions['max']) { - break; - } - if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } @@ -385,7 +379,7 @@ function updateAttribute( size: $size, required: $required, default: $default, - formatOptions: $options ?? null, + formatOptions: $options, newKey: $newKey ?? null ); } catch (TruncateException) { From c062a8f1299d0980ae39130cbb8401aa62933072 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:47:32 +0000 Subject: [PATCH 068/340] Bump console to version 5.2.27 --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 361685d1ed..ad6d883c4c 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -167,7 +167,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:5.2.25 + image: /console:5.2.27 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index ef8d898250..f9a79ee84d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -199,7 +199,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.2.25 + image: appwrite/console:5.2.27 restart: unless-stopped networks: - appwrite From 6be15eee0c9b78cdbbabd4a4068a21684642b6bc Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 28 Nov 2024 11:59:43 +0200 Subject: [PATCH 069/340] try catch not found --- src/Appwrite/Platform/Workers/Databases.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index b027b3e707..f9073465cd 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -11,6 +11,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; @@ -273,6 +274,18 @@ class Databases extends Action if (!$relatedAttribute->isEmpty()) { $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } + + } catch (NotFound $e) { + Console::error($e->getMessage()); + + $dbForProject->deleteDocument('attributes', $attribute->getId()); + + if (!$relatedAttribute->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); + } + + throw $e; + } catch (\Throwable $e) { Console::error($e->getMessage()); From a4ff1bf3bed7c2367596669bca8e35a4562426cf Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 28 Nov 2024 15:47:09 +0545 Subject: [PATCH 070/340] Update storage.php --- app/controllers/api/storage.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 911481a1c0..7d4361a192 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -74,13 +74,14 @@ App::post('/v1/storage/buckets') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); $compression ??= Compression::NONE; + $encryption ??= true; try { $files = (Config::getParam('collections', [])['buckets'] ?? [])['files'] ?? []; if (empty($files)) { @@ -260,7 +261,7 @@ App::put('/v1/storage/buckets/:bucketId') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { From 7e984933245fbeb747b577772ec75901d6c8b457 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 28 Nov 2024 14:08:24 +0400 Subject: [PATCH 071/340] feat: use environment variable to check rules format --- .env | 1 + app/controllers/general.php | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.env b/.env index 8ff8164a21..2470c786b1 100644 --- a/.env +++ b/.env @@ -23,6 +23,7 @@ _APP_OPENSSL_KEY_V1=your-secret-key _APP_DOMAIN=traefik _APP_DOMAIN_FUNCTIONS=functions.localhost _APP_DOMAIN_TARGET=localhost +_APP_RULES_FORMAT=md5 _APP_REDIS_HOST=redis _APP_REDIS_PORT=6379 _APP_REDIS_PASS= diff --git a/app/controllers/general.php b/app/controllers/general.php index 4f38369237..c627d92060 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -56,15 +56,15 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); + } else { $route = Authorization::skip( fn () => $dbForConsole->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) ]) )[0] ?? new Document(); - } else { - $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); } if ($route->isEmpty()) { @@ -528,10 +528,10 @@ App::init() $mainDomain = $envDomain; } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { - $domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]); - } else { + if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); + } else { + $domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]); } $mainDomain = !$domainDocument->isEmpty() ? $domainDocument->getAttribute('domain') : $domain->get(); } @@ -540,18 +540,18 @@ App::init() Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); + } else { $domainDocument = $dbForConsole->findOne('rules', [ Query::equal('domain', [$domain->get()]) ]); - } else { - $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); } if ($domainDocument->isEmpty()) { $domainDocument = new Document([ // TODO: @christyjacob remove once we migrate the rules in 1.7.x - '$id' => version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain->get()), + '$id' => System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain->get()): ID::unique(), 'domain' => $domain->get(), 'resourceType' => 'api', 'status' => 'verifying', From 48d20b2c676a51ec46de3f4cd89167d750f8f4d6 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 28 Nov 2024 14:18:37 +0400 Subject: [PATCH 072/340] feat: update proxy and certificates files --- app/controllers/api/functions.php | 2 +- app/controllers/api/proxy.php | 9 ++++----- src/Appwrite/Platform/Workers/Certificates.php | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 5dc67677ac..3b4b7392b4 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -329,7 +329,7 @@ App::post('/v1/functions') $routeSubdomain = ID::unique(); $domain = "{$routeSubdomain}.{$functionsDomain}"; // TODO: @christyjacob remove once we migrate the rules in 1.7.x - $ruleId = version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain); + $ruleId = System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain) : ID::unique(); $rule = Authorization::skip( fn () => $dbForConsole->createDocument('rules', new Document([ diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 029bc5e8b3..21f1f3ce38 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -61,13 +61,12 @@ App::post('/v1/proxy/rules') } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + $document = $dbForConsole->getDocument('rules', md5($domain)); + } else { $document = $dbForConsole->findOne('rules', [ Query::equal('domain', [$domain]), ]); - } else { - $ruleId = md5($domain); - $document = $dbForConsole->getDocument('rules', $ruleId); } @@ -111,7 +110,7 @@ App::post('/v1/proxy/rules') } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - $ruleId = version_compare(APP_VERSION_STABLE, '1.7.0', '<') ? ID::unique() : md5($domain->get()); + $ruleId = System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain->get()) : ID::unique(); $rule = new Document([ '$id' => $ruleId, diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index db7c73dd0c..e44ab1522f 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -340,12 +340,12 @@ class Certificates extends Action private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (version_compare(APP_VERSION_STABLE, '1.7.0', '<')) { + if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + $rule = $dbForConsole->getDocument('rules', md5($domain)); + } else { $rule = $dbForConsole->findOne('rules', [ Query::equal('domain', [$domain]), ]); - } else { - $rule = $dbForConsole->getDocument('rules', md5($domain)); } if (!$rule->isEmpty()) { From 4dbf11e2360e54329a81707b3bbf8c48c9ef73f0 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 28 Nov 2024 14:33:00 +0400 Subject: [PATCH 073/340] feat: review comments and linter --- app/controllers/api/functions.php | 2 +- app/controllers/api/proxy.php | 4 +- app/controllers/general.php | 8 +- composer.lock | 96 +++++++++---------- .../Platform/Workers/Certificates.php | 2 +- 5 files changed, 56 insertions(+), 56 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 3b4b7392b4..e38dba3f19 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -329,7 +329,7 @@ App::post('/v1/functions') $routeSubdomain = ID::unique(); $domain = "{$routeSubdomain}.{$functionsDomain}"; // TODO: @christyjacob remove once we migrate the rules in 1.7.x - $ruleId = System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain) : ID::unique(); + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); $rule = Authorization::skip( fn () => $dbForConsole->createDocument('rules', new Document([ diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 21f1f3ce38..8ff921ffeb 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -61,7 +61,7 @@ App::post('/v1/proxy/rules') } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { $document = $dbForConsole->getDocument('rules', md5($domain)); } else { $document = $dbForConsole->findOne('rules', [ @@ -110,7 +110,7 @@ App::post('/v1/proxy/rules') } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - $ruleId = System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain->get()) : ID::unique(); + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); $rule = new Document([ '$id' => $ruleId, diff --git a/app/controllers/general.php b/app/controllers/general.php index c627d92060..54e6e1e791 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -56,7 +56,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo } // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); } else { $route = Authorization::skip( @@ -528,7 +528,7 @@ App::init() $mainDomain = $envDomain; } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); } else { $domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]); @@ -540,7 +540,7 @@ App::init() Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); } else { $domainDocument = $dbForConsole->findOne('rules', [ @@ -551,7 +551,7 @@ App::init() if ($domainDocument->isEmpty()) { $domainDocument = new Document([ // TODO: @christyjacob remove once we migrate the rules in 1.7.x - '$id' => System::getEnv('_APP_RULES_FORMAT', null) === 'md5' ? md5($domain->get()): ID::unique(), + '$id' => System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(), 'domain' => $domain->get(), 'resourceType' => 'api', 'status' => 'verifying', diff --git a/composer.lock b/composer.lock index bdb41c2478..317ae6d33e 100644 --- a/composer.lock +++ b/composer.lock @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.28.3", + "version": "v4.29.0", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100" + "reference": "0ef6b2eb74b782f3f9023276c324d22e440f7587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c5c311e0f3d89928251ac5a2f0e3db283612c100", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0ef6b2eb74b782f3f9023276c324d22e440f7587", + "reference": "0ef6b2eb74b782f3f9023276c324d22e440f7587", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.28.3" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.0" }, - "time": "2024-10-22T22:27:17+00:00" + "time": "2024-11-27T18:37:40+00:00" }, { "name": "jean85/pretty-package-versions", @@ -2386,16 +2386,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -2433,7 +2433,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -2449,27 +2449,27 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/http-client", - "version": "v7.1.8", + "version": "v7.1.9", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" + "reference": "2ec49720a38a8041673ba4c42512bfd845218c56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "url": "https://api.github.com/repos/symfony/http-client/zipball/2ec49720a38a8041673ba4c42512bfd845218c56", + "reference": "2ec49720a38a8041673ba4c42512bfd845218c56", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -2527,7 +2527,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.8" + "source": "https://github.com/symfony/http-client/tree/v7.1.9" }, "funding": [ { @@ -2543,20 +2543,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:40:27+00:00" + "time": "2024-11-27T11:52:45+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", "shasum": "" }, "require": { @@ -2605,7 +2605,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" }, "funding": [ { @@ -2621,7 +2621,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-25T12:02:18+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2861,16 +2861,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -2924,7 +2924,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -2940,7 +2940,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "tbachert/spi", @@ -5127,16 +5127,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.2", + "version": "v1.18.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64" + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", - "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", + "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", "shasum": "" }, "require": { @@ -5147,13 +5147,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", + "friendsofphp/php-cs-fixer": "^3.65.0", + "illuminate/view": "^10.48.24", + "larastan/larastan": "^2.9.11", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^1.17.0", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -5189,7 +5189,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-11-20T09:33:46+00:00" + "time": "2024-11-26T15:34:00+00:00" }, { "name": "matthiasmullie/minify", @@ -7800,16 +7800,16 @@ }, { "name": "symfony/options-resolver", - "version": "v7.1.6", + "version": "v7.1.9", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85" + "reference": "0f4099f5306a92487d13b2a4589068c36a93c447" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0f4099f5306a92487d13b2a4589068c36a93c447", + "reference": "0f4099f5306a92487d13b2a4589068c36a93c447", "shasum": "" }, "require": { @@ -7847,7 +7847,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.6" + "source": "https://github.com/symfony/options-resolver/tree/v7.1.9" }, "funding": [ { @@ -7863,7 +7863,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-20T11:08:58+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8557,7 +8557,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index e44ab1522f..4f32877fcf 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -340,7 +340,7 @@ class Certificates extends Action private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void { // TODO: @christyjacob remove once we migrate the rules in 1.7.x - if (System::getEnv('_APP_RULES_FORMAT', null) === 'md5') { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { $rule = $dbForConsole->getDocument('rules', md5($domain)); } else { $rule = $dbForConsole->findOne('rules', [ From b9238936998b1a633b2da5435408f75c8b656ffd Mon Sep 17 00:00:00 2001 From: fogelito Date: Sun, 1 Dec 2024 10:11:19 +0200 Subject: [PATCH 074/340] 0.53.20.hotfix1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e3fbcabc83..676784f1e7 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.20", + "utopia-php/database": "0.53.20.hotfix1", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", From 8349a7e8f73f58dd4cd9d02ca41293bf1aecd8a7 Mon Sep 17 00:00:00 2001 From: fogelito Date: Sun, 1 Dec 2024 10:17:28 +0200 Subject: [PATCH 075/340] lock --- composer.json | 2 +- composer.lock | 123 +++++++++++++++++++++++++------------------------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/composer.json b/composer.json index 676784f1e7..512e203a5e 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.20.hotfix1", + "utopia-php/database": "0.53.200", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 317ae6d33e..e5aacef40c 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": "ae3b9a491c9870a4897cdf712caba1e3", + "content-hash": "fae350df93342992edd8f639948e1570", "packages": [ { "name": "adhocore/jwt", @@ -2343,9 +2343,9 @@ "type": "library", "extra": { "branch-alias": { - "v10.0": "10.0.x-dev", + "v8.3": "8.3.x-dev", "v9.0": "9.0.x-dev", - "v8.3": "8.3.x-dev" + "v10.0": "10.0.x-dev" } }, "autoload": { @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.1.9", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "2ec49720a38a8041673ba4c42512bfd845218c56" + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/2ec49720a38a8041673ba4c42512bfd845218c56", - "reference": "2ec49720a38a8041673ba4c42512bfd845218c56", + "url": "https://api.github.com/repos/symfony/http-client/zipball/955e43336aff03df1e8a8e17daefabb0127a313b", + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b", "shasum": "" }, "require": { @@ -2473,6 +2473,7 @@ "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "amphp/amp": "<2.5", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2483,14 +2484,14 @@ "symfony/http-client-implementation": "3.0" }, "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/messenger": "^6.4|^7.0", @@ -2527,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.9" + "source": "https://github.com/symfony/http-client/tree/v7.2.0" }, "funding": [ { @@ -2543,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2024-11-27T11:52:45+00:00" + "time": "2024-11-29T08:22:02+00:00" }, { "name": "symfony/http-client-contracts", @@ -3475,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.20", + "version": "0.53.200", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04" + "reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/e43f8ee26e06ee8812737e63642dbd7ee7c9dc04", - "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04", + "url": "https://api.github.com/repos/utopia-php/database/zipball/570c63a3760d0e1404679ddfacd9484af40bd9fc", + "reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc", "shasum": "" }, "require": { @@ -3525,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.20" + "source": "https://github.com/utopia-php/database/tree/0.53.200" }, - "time": "2024-11-12T00:23:36+00:00" + "time": "2024-12-01T07:59:15+00:00" }, { "name": "utopia-php/domains", @@ -4362,16 +4363,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.6", + "version": "0.18.7", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071" + "reference": "0d9228faa1c202f9e01483e45a8950485f01a288" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/893ccf06e183f8ece2aed8dbf14d64d6ba036071", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/0d9228faa1c202f9e01483e45a8950485f01a288", + "reference": "0d9228faa1c202f9e01483e45a8950485f01a288", "shasum": "" }, "require": { @@ -4411,9 +4412,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.6" + "source": "https://github.com/utopia-php/storage/tree/0.18.7" }, - "time": "2024-11-06T09:58:50+00:00" + "time": "2024-11-28T11:10:53+00:00" }, { "name": "utopia-php/swoole", @@ -7577,16 +7578,16 @@ }, { "name": "symfony/console", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "url": "https://api.github.com/repos/symfony/console/zipball/23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", "shasum": "" }, "require": { @@ -7650,7 +7651,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.8" + "source": "https://github.com/symfony/console/tree/v7.2.0" }, "funding": [ { @@ -7666,20 +7667,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { @@ -7716,7 +7717,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.6" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -7732,20 +7733,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { @@ -7780,7 +7781,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.6" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -7796,20 +7797,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.9", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0f4099f5306a92487d13b2a4589068c36a93c447" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0f4099f5306a92487d13b2a4589068c36a93c447", - "reference": "0f4099f5306a92487d13b2a4589068c36a93c447", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { @@ -7847,7 +7848,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.9" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -7863,7 +7864,7 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:08:58+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8181,16 +8182,16 @@ }, { "name": "symfony/process", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", "shasum": "" }, "require": { @@ -8222,7 +8223,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.8" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -8238,20 +8239,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/string", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { @@ -8309,7 +8310,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.8" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -8325,7 +8326,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:21+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "textalk/websocket", @@ -8557,7 +8558,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 6e4b365992a2003a9e28f34f5e71a4691568d468 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Mon, 2 Dec 2024 10:39:34 +0100 Subject: [PATCH 076/340] fix(realtime): decrement connectionCounter only if connection is known --- app/realtime.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index 03eaa53bcc..54fd1e05f7 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -678,11 +678,10 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $server->onClose(function (int $connection) use ($realtime, $stats, $register) { if (array_key_exists($connection, $realtime->connections)) { $stats->decr($realtime->connections[$connection]['projectId'], 'connectionsTotal'); + $register->get('telemetry.connectionCounter')->add(-1); } $realtime->unsubscribe($connection); - $register->get('telemetry.connectionCounter')->add(-1); - Console::info('Connection close: ' . $connection); }); From ab900d16d45d81c5677b62d1851c5ce0b5e9424f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 3 Dec 2024 17:19:06 +1300 Subject: [PATCH 077/340] Allow apns content available --- app/controllers/api/messaging.php | 9 +++--- composer.json | 2 +- composer.lock | 33 +++++++++++++-------- src/Appwrite/Platform/Workers/Messaging.php | 4 ++- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e4a627d027..7116d31ba7 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2915,10 +2915,11 @@ App::post('/v1/messaging/messages/push') ->param('action', '', new Text(256), 'Action for push notification.', true) ->param('image', '', new CompoundUID(), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.', true) ->param('icon', '', new Text(256), 'Icon for push notification. Available only for Android and Web Platform.', true) - ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and IOS Platform.', true) + ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and iOS Platform.', true) ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) - ->param('badge', '', new Text(256), 'Badge for push notification. Available only for IOS Platform.', true) + ->param('badge', '', new Text(256), 'Badge for push notification. Available only for iOS Platform.', true) + ->param('contentAvailable', false, new Boolean(), 'Content available for push notification. Available only for iOS Platform.', true) ->param('draft', false, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') @@ -2927,7 +2928,7 @@ App::post('/v1/messaging/messages/push') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $contentAvailable, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -3010,7 +3011,7 @@ App::post('/v1/messaging/messages/push') $pushData = []; - $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge']; + $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge', 'contentAvailable']; foreach ($keys as $key) { if (!empty($$key)) { diff --git a/composer.json b/composer.json index 512e203a5e..7ecf079125 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "utopia-php/image": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "0.12.*", + "utopia-php/messaging": "dev-feat-apns-content-available as 0.12.2", "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", diff --git a/composer.lock b/composer.lock index e5aacef40c..b6e84656b6 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": "fae350df93342992edd8f639948e1570", + "content-hash": "04b9739820be8136d62de48c6325e763", "packages": [ { "name": "adhocore/jwt", @@ -3878,16 +3878,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.12.2", + "version": "dev-feat-apns-content-available", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9" + "reference": "2580b8357d2dde6ed567a52e5164cfe58fb9b6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/f6790fba1fcee12163d51c65d2c226a7856295d9", - "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2580b8357d2dde6ed567a52e5164cfe58fb9b6dd", + "reference": "2580b8357d2dde6ed567a52e5164cfe58fb9b6dd", "shasum": "" }, "require": { @@ -3898,9 +3898,9 @@ "phpmailer/phpmailer": "6.9.1" }, "require-dev": { - "laravel/pint": "1.13.11", - "phpstan/phpstan": "1.10.58", - "phpunit/phpunit": "10.5.10" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*" }, "type": "library", "autoload": { @@ -3923,9 +3923,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.12.2" + "source": "https://github.com/utopia-php/messaging/tree/feat-apns-content-available" }, - "time": "2024-10-22T01:02:20+00:00" + "time": "2024-12-03T04:09:05+00:00" }, { "name": "utopia-php/migration", @@ -8556,9 +8556,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/messaging", + "version": "dev-feat-apns-content-available", + "alias": "0.12.2", + "alias_normalized": "0.12.2.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/messaging": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 58f6265ff4..5dee0fa72f 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -686,6 +686,7 @@ class Messaging extends Action $color = $message['data']['color'] ?? null; $tag = $message['data']['tag'] ?? null; $badge = $message['data']['badge'] ?? null; + $contentAvailable = $message['data']['contentAvailable'] ?? false; return new Push( $to, @@ -698,7 +699,8 @@ class Messaging extends Action $icon, $color, $tag, - $badge + $badge, + $contentAvailable ); } From fa49244b4b9ea481af6f61d8dfeeefdcd6e9c965 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 3 Dec 2024 22:50:40 +1300 Subject: [PATCH 078/340] Fix param type --- app/controllers/api/messaging.php | 2 +- src/Appwrite/Platform/Workers/Messaging.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 7116d31ba7..54b3eb83cb 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2918,7 +2918,7 @@ App::post('/v1/messaging/messages/push') ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and iOS Platform.', true) ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) - ->param('badge', '', new Text(256), 'Badge for push notification. Available only for iOS Platform.', true) + ->param('badge', 0, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) ->param('contentAvailable', false, new Boolean(), 'Content available for push notification. Available only for iOS Platform.', true) ->param('draft', false, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 5dee0fa72f..3edb0c2aed 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -333,7 +333,6 @@ class Messaging extends Action $message->setAttribute('status', MessageStatus::SENT); } - $message->removeAttribute('to'); foreach ($providers as $provider) { From a4611985476c5b8129f92bd3f66dcfc84e241705 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 4 Dec 2024 19:27:55 +1300 Subject: [PATCH 079/340] Add critical and priority params --- app/controllers/api/messaging.php | 25 +++++++++++++++++---- composer.lock | 8 +++---- src/Appwrite/Platform/Workers/Messaging.php | 10 ++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 54b3eb83cb..45eba6e434 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2919,7 +2919,9 @@ App::post('/v1/messaging/messages/push') ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) ->param('badge', 0, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) - ->param('contentAvailable', false, new Boolean(), 'Content available for push notification. Available only for iOS Platform.', true) + ->param('contentAvailable', false, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) + ->param('critical', false, new Boolean(), 'If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.', true) + ->param('priority', 'high', new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) ->param('draft', false, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') @@ -2928,7 +2930,7 @@ App::post('/v1/messaging/messages/push') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $contentAvailable, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $contentAvailable, bool $critical, string $priority, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -3011,7 +3013,7 @@ App::post('/v1/messaging/messages/push') $pushData = []; - $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge', 'contentAvailable']; + $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge', 'contentAvailable', 'critical', 'priority']; foreach ($keys as $key) { if (!empty($$key)) { @@ -3697,6 +3699,9 @@ App::patch('/v1/messaging/messages/push/:messageId') ->param('color', null, new Text(256), 'Color for push notification. Available only for Android platforms.', true) ->param('tag', null, new Text(256), 'Tag for push notification. Available only for Android platforms.', true) ->param('badge', null, new Integer(), 'Badge for push notification. Available only for iOS platforms.', true) + ->param('contentAvailable', null, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) + ->param('critical', null, new Boolean(), 'If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.', true) + ->param('priority', null, new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) ->param('draft', null, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') @@ -3705,7 +3710,7 @@ App::patch('/v1/messaging/messages/push/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $contentAvailable, ?bool $critical, ?string $priority, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3844,6 +3849,18 @@ App::patch('/v1/messaging/messages/push/:messageId') $pushData['badge'] = $badge; } + if (!\is_null($contentAvailable)) { + $pushData['contentAvailable'] = $contentAvailable; + } + + if (!\is_null($critical)) { + $pushData['critical'] = $critical; + } + + if (!\is_null($priority)) { + $pushData['priority'] = $priority; + } + if (!\is_null($image)) { [$bucketId, $fileId] = CompoundUID::parse($image); diff --git a/composer.lock b/composer.lock index b6e84656b6..8cddc64940 100644 --- a/composer.lock +++ b/composer.lock @@ -3882,12 +3882,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "2580b8357d2dde6ed567a52e5164cfe58fb9b6dd" + "reference": "02ccc85424eabb680b5a2f1458a471f19bac56c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2580b8357d2dde6ed567a52e5164cfe58fb9b6dd", - "reference": "2580b8357d2dde6ed567a52e5164cfe58fb9b6dd", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/02ccc85424eabb680b5a2f1458a471f19bac56c0", + "reference": "02ccc85424eabb680b5a2f1458a471f19bac56c0", "shasum": "" }, "require": { @@ -3925,7 +3925,7 @@ "issues": "https://github.com/utopia-php/messaging/issues", "source": "https://github.com/utopia-php/messaging/tree/feat-apns-content-available" }, - "time": "2024-12-03T04:09:05+00:00" + "time": "2024-12-03T09:44:33+00:00" }, { "name": "utopia-php/migration", diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 3edb0c2aed..a5339c3764 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -32,6 +32,7 @@ use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Messages\Email\Attachment; use Utopia\Messaging\Messages\Push; use Utopia\Messaging\Messages\SMS; +use Utopia\Messaging\Priority; use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\Storage\Device; @@ -686,6 +687,11 @@ class Messaging extends Action $tag = $message['data']['tag'] ?? null; $badge = $message['data']['badge'] ?? null; $contentAvailable = $message['data']['contentAvailable'] ?? false; + $critical = $message['data']['critical'] ?? false; + + $priority = $message['data']['priority'] === 'normal' + ? Priority::NORMAL + : Priority::HIGH; return new Push( $to, @@ -699,7 +705,9 @@ class Messaging extends Action $color, $tag, $badge, - $contentAvailable + $contentAvailable, + $critical, + $priority ); } From 2934bdbd3ba7b223a90f5ca93d9711f69eba5832 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 4 Dec 2024 20:16:13 +1300 Subject: [PATCH 080/340] Update messaging --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 8cddc64940..dadea47a55 100644 --- a/composer.lock +++ b/composer.lock @@ -3882,12 +3882,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "02ccc85424eabb680b5a2f1458a471f19bac56c0" + "reference": "4947ee3819a28aea303456a462051601e4d12ec9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/02ccc85424eabb680b5a2f1458a471f19bac56c0", - "reference": "02ccc85424eabb680b5a2f1458a471f19bac56c0", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/4947ee3819a28aea303456a462051601e4d12ec9", + "reference": "4947ee3819a28aea303456a462051601e4d12ec9", "shasum": "" }, "require": { @@ -3925,7 +3925,7 @@ "issues": "https://github.com/utopia-php/messaging/issues", "source": "https://github.com/utopia-php/messaging/tree/feat-apns-content-available" }, - "time": "2024-12-03T09:44:33+00:00" + "time": "2024-12-04T07:10:23+00:00" }, { "name": "utopia-php/migration", From 968b16d8bf0e804ed9d36a6b4e5bda483d796fee Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 4 Dec 2024 08:38:26 +0000 Subject: [PATCH 081/340] upgrade utopia storage --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index e5aacef40c..d58556613a 100644 --- a/composer.lock +++ b/composer.lock @@ -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", @@ -8558,7 +8558,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From f4917f7bc6a18e98d71a036bc68734855623cded Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 5 Dec 2024 17:04:11 +1300 Subject: [PATCH 082/340] Reorder params --- app/controllers/api/messaging.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 45eba6e434..394f836164 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2906,12 +2906,12 @@ App::post('/v1/messaging/messages/push') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('title', '', new Text(256), 'Title for push notification.') - ->param('body', '', new Text(64230), 'Body for push notification.') + ->param('title', null, new Text(256), 'Title for push notification.', true) + ->param('body', null, new Text(64230), 'Body for push notification.', true) ->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true) ->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true) - ->param('data', null, new JSON(), 'Additional Data for push notification.', true) + ->param('data', null, new JSON(), 'Additional key-value pair data for push notification.', true) ->param('action', '', new Text(256), 'Action for push notification.', true) ->param('image', '', new CompoundUID(), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.', true) ->param('icon', '', new Text(256), 'Icon for push notification. Available only for Android and Web Platform.', true) @@ -2919,18 +2919,18 @@ App::post('/v1/messaging/messages/push') ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) ->param('badge', 0, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) + ->param('draft', false, new Boolean(), 'Is message a draft', true) + ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->param('contentAvailable', false, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) ->param('critical', false, new Boolean(), 'If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.', true) ->param('priority', 'high', new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) - ->param('draft', false, new Boolean(), 'Is message a draft', true) - ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('dbForConsole') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $contentAvailable, bool $critical, string $priority, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?string $title, ?string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -3699,18 +3699,18 @@ App::patch('/v1/messaging/messages/push/:messageId') ->param('color', null, new Text(256), 'Color for push notification. Available only for Android platforms.', true) ->param('tag', null, new Text(256), 'Tag for push notification. Available only for Android platforms.', true) ->param('badge', null, new Integer(), 'Badge for push notification. Available only for iOS platforms.', true) + ->param('draft', null, new Boolean(), 'Is message a draft', true) + ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->param('contentAvailable', null, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) ->param('critical', null, new Boolean(), 'If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.', true) ->param('priority', null, new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) - ->param('draft', null, new Boolean(), 'Is message a draft', true) - ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('dbForConsole') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $contentAvailable, ?bool $critical, ?string $priority, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, ?bool $contentAvailable, ?bool $critical, ?string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { From 98149f56b51e85a56746ca6ecaf808d525fc2359 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 5 Dec 2024 17:20:20 +1300 Subject: [PATCH 083/340] Default empty title and body --- app/controllers/api/messaging.php | 6 +++--- src/Appwrite/Platform/Workers/Messaging.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 394f836164..dea43add26 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2906,8 +2906,8 @@ App::post('/v1/messaging/messages/push') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('title', null, new Text(256), 'Title for push notification.', true) - ->param('body', null, new Text(64230), 'Body for push notification.', true) + ->param('title', '', new Text(256), 'Title for push notification.', true) + ->param('body', '', new Text(64230), 'Body for push notification.', true) ->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true) ->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true) @@ -2930,7 +2930,7 @@ App::post('/v1/messaging/messages/push') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?string $title, ?string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index a5339c3764..e3febc72d6 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -676,8 +676,8 @@ class Messaging extends Action private function buildPushMessage(Document $message): Push { $to = $message['to']; - $title = $message['data']['title']; - $body = $message['data']['body']; + $title = $message['data']['title'] === '' ? null : $message['data']['title']; + $body = $message['data']['body'] === '' ? null : $message['data']['body']; $data = $message['data']['data'] ?? null; $action = $message['data']['action'] ?? null; $image = $message['data']['image']['url'] ?? null; From 526f54cf06515b1eeff4aad5d6c73e284a277671 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 5 Dec 2024 21:09:52 +1300 Subject: [PATCH 084/340] Update src/Appwrite/Platform/Workers/Messaging.php Co-authored-by: Damodar Lohani --- src/Appwrite/Platform/Workers/Messaging.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index e3febc72d6..76e1ad3572 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -689,9 +689,9 @@ class Messaging extends Action $contentAvailable = $message['data']['contentAvailable'] ?? false; $critical = $message['data']['critical'] ?? false; - $priority = $message['data']['priority'] === 'normal' - ? Priority::NORMAL - : Priority::HIGH; + $priority = $message['data']['priority'] === 'high' + ? Priority::HIGH + : Priority::NORMAL; return new Push( $to, From 5b75fcc39814bfdd9b2e3f9d46ea28a953431663 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 5 Dec 2024 21:39:43 +1300 Subject: [PATCH 085/340] Update lock --- composer.json | 2 +- composer.lock | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index 7ecf079125..71fcb358f6 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "utopia-php/image": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "dev-feat-apns-content-available as 0.12.2", + "utopia-php/messaging": "0.13.*", "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", diff --git a/composer.lock b/composer.lock index dadea47a55..5d84cfb223 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": "04b9739820be8136d62de48c6325e763", + "content-hash": "d54809ddf7cd4b318f4606b56827037e", "packages": [ { "name": "adhocore/jwt", @@ -3878,16 +3878,16 @@ }, { "name": "utopia-php/messaging", - "version": "dev-feat-apns-content-available", + "version": "0.13.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "4947ee3819a28aea303456a462051601e4d12ec9" + "reference": "0e3e57351fe4fe875ef3ab9a01a7fff5f022de90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/4947ee3819a28aea303456a462051601e4d12ec9", - "reference": "4947ee3819a28aea303456a462051601e4d12ec9", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/0e3e57351fe4fe875ef3ab9a01a7fff5f022de90", + "reference": "0e3e57351fe4fe875ef3ab9a01a7fff5f022de90", "shasum": "" }, "require": { @@ -3923,9 +3923,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/feat-apns-content-available" + "source": "https://github.com/utopia-php/messaging/tree/0.13.0" }, - "time": "2024-12-04T07:10:23+00:00" + "time": "2024-12-05T08:36:07+00:00" }, { "name": "utopia-php/migration", @@ -8556,18 +8556,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/messaging", - "version": "dev-feat-apns-content-available", - "alias": "0.12.2", - "alias_normalized": "0.12.2.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/messaging": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 45f6d9c0b9c18058b7204dd19d7f6626054ba08c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 5 Dec 2024 23:12:06 +1300 Subject: [PATCH 086/340] Specs --- app/config/specs/open-api3-latest-client.json | 2 +- .../specs/open-api3-latest-console.json | 66 +++++++++++++--- app/config/specs/open-api3-latest-server.json | 66 +++++++++++++--- app/config/specs/swagger2-latest-client.json | 2 +- app/config/specs/swagger2-latest-console.json | 78 +++++++++++++++---- app/config/specs/swagger2-latest-server.json | 78 +++++++++++++++---- 6 files changed, 236 insertions(+), 56 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index d948a101f2..1013698073 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index fb01509ecd..32985d9c58 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -9488,7 +9488,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10145,7 +10146,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -14120,7 +14122,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -14140,7 +14142,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "" }, "color": { @@ -14154,9 +14156,9 @@ "x-example": "" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -14167,12 +14169,31 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -14331,6 +14352,27 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -35109,7 +35151,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 1504322456..12d1337c5e 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8596,7 +8596,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9019,7 +9020,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12978,7 +12980,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -12998,7 +13000,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "" }, "color": { @@ -13012,9 +13014,9 @@ "x-example": "" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -13025,12 +13027,31 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -13190,6 +13211,27 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -25746,7 +25788,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 3ac70ffe28..4b6366f2bf 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 25c0c289b3..a51fc316cb 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -9610,7 +9610,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10286,7 +10287,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -14328,13 +14330,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -14366,7 +14368,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -14390,7 +14392,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -14407,10 +14409,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": 0, + "x-example": null }, "draft": { "type": "boolean", @@ -14423,12 +14425,34 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -14600,6 +14624,30 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -35618,7 +35666,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 68bcf268fb..5a06a27a63 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8720,7 +8720,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9166,7 +9167,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13194,13 +13196,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -13232,7 +13234,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -13256,7 +13258,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -13273,10 +13275,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": 0, + "x-example": null }, "draft": { "type": "boolean", @@ -13289,12 +13291,34 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -13467,6 +13491,30 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -26233,7 +26281,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { From 2c87e3f4e5b96a0a55491e05b4cba55264675654 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:51:24 +0000 Subject: [PATCH 087/340] feat: delete git folder --- src/Appwrite/Platform/Workers/Builds.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 5dd2f7f886..19ff83acd2 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -209,8 +209,7 @@ class Builds extends Action try { if ($isNewBuild && !$isVcsEnabled) { - // Non-vcs+Template - + // Non-VCS + Template $templateRepositoryName = $template->getAttribute('repositoryName', ''); $templateOwnerName = $template->getAttribute('ownerName', ''); $templateVersion = $template->getAttribute('version', ''); @@ -233,6 +232,8 @@ class Builds extends Action throw new \Exception('Unable to clone code repository: ' . $stderr); } + Console::execute('find ' . \escapeshellarg($tmpTemplateDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); + // Ensure directories Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); @@ -398,6 +399,8 @@ class Builds extends Action 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); + $tarParamDirectory = '/tmp/builds/' . $buildId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax From 44d3a4f22349a8fdc8958abcbe2d2bc0b8651a37 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Mon, 9 Dec 2024 15:42:20 +1300 Subject: [PATCH 088/340] Update specs --- app/config/specs/open-api3-1.6.x-client.json | 4 +- app/config/specs/open-api3-1.6.x-console.json | 68 +++++++++++++--- app/config/specs/open-api3-1.6.x-server.json | 68 +++++++++++++--- app/config/specs/swagger2-1.6.x-client.json | 4 +- app/config/specs/swagger2-1.6.x-console.json | 80 +++++++++++++++---- app/config/specs/swagger2-1.6.x-server.json | 80 +++++++++++++++---- src/Appwrite/Platform/Workers/Messaging.php | 9 +-- 7 files changed, 246 insertions(+), 67 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 e3cd909b4e..1013698073 100644 --- a/app/config/specs/open-api3-1.6.x-client.json +++ b/app/config/specs/open-api3-1.6.x-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2784,7 +2784,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", 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 369fea741a..32985d9c58 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2795,7 +2795,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -9488,7 +9488,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10145,7 +10146,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -14120,7 +14122,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -14140,7 +14142,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "<SOUND>" }, "color": { @@ -14154,9 +14156,9 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -14167,12 +14169,31 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -14331,6 +14352,27 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -35109,7 +35151,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { 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 e84b751743..12d1337c5e 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2451,7 +2451,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -8596,7 +8596,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9019,7 +9020,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12978,7 +12980,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -12998,7 +13000,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "<SOUND>" }, "color": { @@ -13012,9 +13014,9 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -13025,12 +13027,31 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -13190,6 +13211,27 @@ "type": "string", "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -25746,7 +25788,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-1.6.x-client.json b/app/config/specs/swagger2-1.6.x-client.json index b1b9ce8dca..4b6366f2bf 100644 --- a/app/config/specs/swagger2-1.6.x-client.json +++ b/app/config/specs/swagger2-1.6.x-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2922,7 +2922,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index 9ce9d5f60d..a51fc316cb 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2949,7 +2949,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -9610,7 +9610,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10286,7 +10287,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -14328,13 +14330,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -14366,7 +14368,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -14390,7 +14392,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -14407,10 +14409,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": 0, + "x-example": null }, "draft": { "type": "boolean", @@ -14423,12 +14425,34 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -14600,6 +14624,30 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -35618,7 +35666,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 2c8e80c65e..5a06a27a63 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2604,7 +2604,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -8720,7 +8720,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9166,7 +9167,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13194,13 +13196,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -13232,7 +13234,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -13256,7 +13258,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -13273,10 +13275,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": 0, + "x-example": null }, "draft": { "type": "boolean", @@ -13289,12 +13291,34 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } }, "required": [ - "messageId", - "title", - "body" + "messageId" ] } } @@ -13467,6 +13491,30 @@ "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", "default": null, "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": null, + "x-enum-keys": [] } } } @@ -26233,7 +26281,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 76e1ad3572..1de503cd9a 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -276,7 +276,7 @@ class Messaging extends Action Query::equal('identifier', [$result['recipient']]) ]); - if ($target instanceof Document && !$target->isEmpty()) { + if (!$target->isEmpty()) { $dbForProject->updateDocument( 'targets', $target->getId(), @@ -288,7 +288,7 @@ class Messaging extends Action } catch (\Throwable $e) { $deliveryErrors[] = 'Failed sending to targets with error: ' . $e->getMessage(); } finally { - $errorTotal = count($deliveryErrors); + $errorTotal = \count($deliveryErrors); $queueForUsage ->setProject($project) ->addMetric(METRIC_MESSAGES, ($deliveredTotal + $errorTotal)) @@ -676,8 +676,8 @@ class Messaging extends Action private function buildPushMessage(Document $message): Push { $to = $message['to']; - $title = $message['data']['title'] === '' ? null : $message['data']['title']; - $body = $message['data']['body'] === '' ? null : $message['data']['body']; + $title = ($message['data']['title'] ?? null) === '' ? null : $message['data']['title']; + $body = ($message['data']['body'] ?? null) === '' ? null : $message['data']['body']; $data = $message['data']['data'] ?? null; $action = $message['data']['action'] ?? null; $image = $message['data']['image']['url'] ?? null; @@ -688,7 +688,6 @@ class Messaging extends Action $badge = $message['data']['badge'] ?? null; $contentAvailable = $message['data']['contentAvailable'] ?? false; $critical = $message['data']['critical'] ?? false; - $priority = $message['data']['priority'] === 'high' ? Priority::HIGH : Priority::NORMAL; From 5ffb81df43f6384c14bc9fbb81f0092f6a6b621e Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 9 Dec 2024 17:42:05 +0200 Subject: [PATCH 089/340] update usage project attr --- src/Appwrite/Platform/Workers/Usage.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 034e558d5d..ce2cb3ff52 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -15,9 +15,10 @@ class Usage extends Action { private array $stats = []; private int $lastTriggeredTime = 0; + private int $aggregationInterval = 20; private int $keys = 0; private const INFINITY_PERIOD = '_inf_'; - private const KEYS_THRESHOLD = 10000; + private const KEYS_THRESHOLD = 12000; public static function getName(): string { @@ -39,6 +40,7 @@ class Usage extends Action $this->action($message, $getProjectDB, $queueForUsageDump); }); + $this->aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); $this->lastTriggeredTime = time(); } @@ -56,9 +58,7 @@ class Usage extends Action if (empty($payload)) { throw new Exception('Missing payload'); } - //Todo Figure out way to preserve keys when the container is being recreated @shimonewman - $aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); $project = new Document($payload['project'] ?? []); $projectId = $project->getInternalId(); foreach ($payload['reduce'] ?? [] as $document) { @@ -74,7 +74,11 @@ class Usage extends Action ); } - $this->stats[$projectId]['project'] = $project; + $this->stats[$projectId]['project'] = [ + '$uid' => $project->getId(), + '$internalId' => $project->getInternalId(), + 'database' => $project->getAttribute('database'), + ]; $this->stats[$projectId]['receivedAt'] = DateTime::now(); foreach ($payload['metrics'] ?? [] as $metric) { $this->keys++; @@ -89,7 +93,7 @@ class Usage extends Action // If keys crossed threshold or X time passed since the last send and there are some keys in the array ($this->stats) if ( $this->keys >= self::KEYS_THRESHOLD || - (time() - $this->lastTriggeredTime > $aggregationInterval && $this->keys > 0) + (time() - $this->lastTriggeredTime > $this->aggregationInterval && $this->keys > 0) ) { Console::warning('[' . DateTime::now() . '] Aggregated ' . $this->keys . ' keys'); From 8649032b734ac9a40db08d31bcec1df752a2e814 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 22:52:39 +1300 Subject: [PATCH 090/340] Fix badge param type --- app/controllers/api/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index dea43add26..28bc9d2896 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2930,7 +2930,7 @@ App::post('/v1/messaging/messages/push') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, int $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; From 15855e2406d1763648dd0e15208a098d9bd94d1b Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 22:53:03 +1300 Subject: [PATCH 091/340] Fix message search builder subquery --- app/init.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/init.php b/app/init.php index 30ece74553..059fb412f7 100644 --- a/app/init.php +++ b/app/init.php @@ -721,12 +721,19 @@ Database::addFilter( $data = \json_decode($message->getAttribute('data', []), true); $providerType = $message->getAttribute('providerType', ''); - if ($providerType === MESSAGE_TYPE_EMAIL) { - $searchValues = \array_merge($searchValues, [$data['subject'], MESSAGE_TYPE_EMAIL]); - } elseif ($providerType === MESSAGE_TYPE_SMS) { - $searchValues = \array_merge($searchValues, [$data['content'], MESSAGE_TYPE_SMS]); - } else { - $searchValues = \array_merge($searchValues, [$data['title'], MESSAGE_TYPE_PUSH]); + switch ($providerType) { + case MESSAGE_TYPE_EMAIL: + $searchValues[] = $data['subject']; + $searchValues[] = MESSAGE_TYPE_EMAIL; + break; + case MESSAGE_TYPE_SMS: + $searchValues[] = $data['content']; + $searchValues[] = MESSAGE_TYPE_SMS; + break; + case MESSAGE_TYPE_PUSH: + $searchValues[] = $data['title'] ?? ''; + $searchValues[] = MESSAGE_TYPE_PUSH; + break; } $search = \implode(' ', \array_filter($searchValues)); From f2b202aa52548dfd034cd5d078b1570e93dbba13 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 22:53:40 +1300 Subject: [PATCH 092/340] Update push message builder --- src/Appwrite/Platform/Workers/Messaging.php | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 1de503cd9a..8e60425da3 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -676,8 +676,8 @@ class Messaging extends Action private function buildPushMessage(Document $message): Push { $to = $message['to']; - $title = ($message['data']['title'] ?? null) === '' ? null : $message['data']['title']; - $body = ($message['data']['body'] ?? null) === '' ? null : $message['data']['body']; + $title = $message['data']['title'] ?? null; + $body = $message['data']['body'] ?? null; $data = $message['data']['data'] ?? null; $action = $message['data']['action'] ?? null; $image = $message['data']['image']['url'] ?? null; @@ -686,11 +686,21 @@ class Messaging extends Action $color = $message['data']['color'] ?? null; $tag = $message['data']['tag'] ?? null; $badge = $message['data']['badge'] ?? null; - $contentAvailable = $message['data']['contentAvailable'] ?? false; - $critical = $message['data']['critical'] ?? false; - $priority = $message['data']['priority'] === 'high' - ? Priority::HIGH - : Priority::NORMAL; + $contentAvailable = $message['data']['contentAvailable'] ?? null; + $critical = $message['data']['critical'] ?? null; + $priority = $message['data']['priority'] ?? null; + + if ($title === '') { + $title = null; + } + if ($body === '') { + $body = null; + } + if ($priority !== null) { + $priority = $priority === 'high' + ? Priority::HIGH + : Priority::NORMAL; + } return new Push( $to, From 30fed93e2aa76259395e453821d143fe6ab112eb Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 23:33:49 +1300 Subject: [PATCH 093/340] Remove variable variable usage --- app/controllers/api/messaging.php | 44 ++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 28bc9d2896..6c5fdf6df3 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -3013,12 +3013,44 @@ App::post('/v1/messaging/messages/push') $pushData = []; - $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge', 'contentAvailable', 'critical', 'priority']; - - foreach ($keys as $key) { - if (!empty($$key)) { - $pushData[$key] = $$key; - } + if (!empty($title)) { + $pushData['title'] = $title; + } + if (!empty($body)) { + $pushData['body'] = $body; + } + if (!empty($data)) { + $pushData['data'] = $data; + } + if (!empty($action)) { + $pushData['action'] = $action; + } + if (!empty($image)) { + $pushData['image'] = $image; + } + if (!empty($icon)) { + $pushData['icon'] = $icon; + } + if (!empty($sound)) { + $pushData['sound'] = $sound; + } + if (!empty($color)) { + $pushData['color'] = $color; + } + if (!empty($tag)) { + $pushData['tag'] = $tag; + } + if ($badge >= 0) { + $pushData['badge'] = $badge; + } + if ($contentAvailable) { + $pushData['contentAvailable'] = true; + } + if ($critical) { + $pushData['critical'] = true; + } + if (!empty($priority)) { + $pushData['priority'] = $priority; } $message = $dbForProject->createDocument('messages', new Document([ From 6c83eba693089b9928b1b5fd9e3b83c7c7864400 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 23:34:24 +1300 Subject: [PATCH 094/340] Fix badge default to allow sending clear badge notifications --- app/controllers/api/messaging.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 6c5fdf6df3..fe75a0529b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2918,12 +2918,12 @@ App::post('/v1/messaging/messages/push') ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and iOS Platform.', true) ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) - ->param('badge', 0, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) + ->param('badge', -1, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) ->param('draft', false, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->param('contentAvailable', false, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) ->param('critical', false, new Boolean(), 'If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.', true) - ->param('priority', 'high', new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) + ->param('priority', 'high', new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device state and may not deliver notifications immediately. "high" will always attempt to immediately deliver the notification.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('dbForConsole') From 636dc8fe9faef5de29f57be8f045b02d48928cbf Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Dec 2024 23:53:56 +1300 Subject: [PATCH 095/340] Update specs --- app/config/specs/open-api3-1.6.x-console.json | 2 +- app/config/specs/open-api3-1.6.x-server.json | 2 +- app/config/specs/open-api3-latest-console.json | 2 +- app/config/specs/open-api3-latest-server.json | 2 +- app/config/specs/swagger2-1.6.x-console.json | 4 ++-- app/config/specs/swagger2-1.6.x-server.json | 4 ++-- app/config/specs/swagger2-latest-console.json | 4 ++-- app/config/specs/swagger2-latest-server.json | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) 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 32985d9c58..a9e502c1dd 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -14182,7 +14182,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "x-example": "normal", "enum": [ "normal", 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 12d1337c5e..38a0fe242b 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -13040,7 +13040,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "x-example": "normal", "enum": [ "normal", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 32985d9c58..a9e502c1dd 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -14182,7 +14182,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "x-example": "normal", "enum": [ "normal", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 12d1337c5e..38a0fe242b 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -13040,7 +13040,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "x-example": "normal", "enum": [ "normal", diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index a51fc316cb..c62d82fac7 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -14411,7 +14411,7 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "default": 0, + "default": -1, "x-example": null }, "draft": { @@ -14440,7 +14440,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "default": "high", "x-example": "normal", "enum": [ diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 5a06a27a63..4336313588 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -13277,7 +13277,7 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "default": 0, + "default": -1, "x-example": null }, "draft": { @@ -13306,7 +13306,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "default": "high", "x-example": "normal", "enum": [ diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index a51fc316cb..c62d82fac7 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -14411,7 +14411,7 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "default": 0, + "default": -1, "x-example": null }, "draft": { @@ -14440,7 +14440,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "default": "high", "x-example": "normal", "enum": [ diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 5a06a27a63..4336313588 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -13277,7 +13277,7 @@ "badge": { "type": "integer", "description": "Badge for push notification. Available only for iOS Platform.", - "default": 0, + "default": -1, "x-example": null }, "draft": { @@ -13306,7 +13306,7 @@ }, "priority": { "type": "string", - "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", "default": "high", "x-example": "normal", "enum": [ From 478e19f52fc8df3bfcfca025c0cbe8d8334d6c46 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Dec 2024 00:26:01 +1300 Subject: [PATCH 096/340] Map push priority enum name --- app/config/specs/open-api3-1.6.x-console.json | 4 ++-- app/config/specs/open-api3-1.6.x-server.json | 4 ++-- app/config/specs/open-api3-latest-console.json | 4 ++-- app/config/specs/open-api3-latest-server.json | 4 ++-- app/config/specs/swagger2-1.6.x-console.json | 4 ++-- app/config/specs/swagger2-1.6.x-server.json | 4 ++-- app/config/specs/swagger2-latest-console.json | 4 ++-- app/config/specs/swagger2-latest-server.json | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) 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 a9e502c1dd..3c16ebc066 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -14188,7 +14188,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -14371,7 +14371,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } 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 38a0fe242b..75ff222ee6 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -13046,7 +13046,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -13230,7 +13230,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index a9e502c1dd..3c16ebc066 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -14188,7 +14188,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -14371,7 +14371,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 38a0fe242b..75ff222ee6 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -13046,7 +13046,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -13230,7 +13230,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index c62d82fac7..5e42b84478 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -14447,7 +14447,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -14646,7 +14646,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 4336313588..3aa1139c09 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -13313,7 +13313,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -13513,7 +13513,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index c62d82fac7..5e42b84478 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -14447,7 +14447,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -14646,7 +14646,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 4336313588..3aa1139c09 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -13313,7 +13313,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } }, @@ -13513,7 +13513,7 @@ "normal", "high" ], - "x-enum-name": null, + "x-enum-name": "MessagePriority", "x-enum-keys": [] } } From 4a49629a34359bcd9cde7649c109e9d822348a7e Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Dec 2024 00:26:58 +1300 Subject: [PATCH 097/340] Map enum --- src/Appwrite/Specification/Format.php | 2 ++ src/Appwrite/Specification/Format/Swagger2.php | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index 30ce6470e1..8396f5cb7c 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -215,6 +215,8 @@ abstract class Format switch ($param) { case 'status': return 'MessageStatus'; + case 'priority': + return 'MessagePriority'; } break; case 'createSmtpProvider': diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 66a540a4d4..b10188525e 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -34,7 +34,6 @@ class Swagger2 extends Format foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); - continue; } } } @@ -46,7 +45,6 @@ class Swagger2 extends Format foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); - continue; } } } From f2027bad2ca5dcd7dfcfd1174ffd25b73ed1e1aa Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:12:20 +0000 Subject: [PATCH 098/340] chore: bump composer --- composer.lock | 296 +++++++++++++++++++++++++------------------------- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/composer.lock b/composer.lock index 14eb289fa1..d31ecfa317 100644 --- a/composer.lock +++ b/composer.lock @@ -708,16 +708,16 @@ }, { "name": "google/protobuf", - "version": "v4.28.3", + "version": "v4.29.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100" + "reference": "6042b5483f8029e42473faeb8ef75ba266278381" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c5c311e0f3d89928251ac5a2f0e3db283612c100", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/6042b5483f8029e42473faeb8ef75ba266278381", + "reference": "6042b5483f8029e42473faeb8ef75ba266278381", "shasum": "" }, "require": { @@ -746,34 +746,34 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.28.3" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.1" }, - "time": "2024-10-22T22:27:17+00:00" + "time": "2024-12-03T22:07:45+00:00" }, { "name": "jean85/pretty-package-versions", - "version": "2.0.6", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", "extra": { @@ -805,9 +805,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0" }, - "time": "2024-03-08T09:58:59+00:00" + "time": "2024-11-18T16:19:46+00:00" }, { "name": "league/csv", @@ -2342,9 +2342,9 @@ "type": "library", "extra": { "branch-alias": { - "v10.0": "10.0.x-dev", + "v8.3": "8.3.x-dev", "v9.0": "9.0.x-dev", - "v8.3": "8.3.x-dev" + "v10.0": "10.0.x-dev" } }, "autoload": { @@ -2385,16 +2385,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -2432,7 +2432,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -2448,30 +2448,31 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/http-client", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "url": "https://api.github.com/repos/symfony/http-client/zipball/955e43336aff03df1e8a8e17daefabb0127a313b", + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "amphp/amp": "<2.5", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2482,14 +2483,14 @@ "symfony/http-client-implementation": "3.0" }, "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/messenger": "^6.4|^7.0", @@ -2526,7 +2527,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.8" + "source": "https://github.com/symfony/http-client/tree/v7.2.0" }, "funding": [ { @@ -2542,20 +2543,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:40:27+00:00" + "time": "2024-11-29T08:22:02+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", "shasum": "" }, "require": { @@ -2563,12 +2564,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": { @@ -2604,7 +2605,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" }, "funding": [ { @@ -2620,7 +2621,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-25T12:02:18+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2722,8 +2723,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2802,8 +2803,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2860,16 +2861,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -2923,7 +2924,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -2939,7 +2940,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "tbachert/spi", @@ -2968,10 +2969,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": { @@ -3676,16 +3677,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.12", + "version": "0.33.15", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f" + "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/bfb7812df9e489b3cba7d5504a49ce578c71af1f", - "reference": "bfb7812df9e489b3cba7d5504a49ce578c71af1f", + "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", + "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", "shasum": "" }, "require": { @@ -3717,9 +3718,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.12" + "source": "https://github.com/utopia-php/http/tree/0.33.15" }, - "time": "2024-11-13T12:45:45+00:00" + "time": "2024-12-10T13:07:04+00:00" }, { "name": "utopia-php/image", @@ -4353,16 +4354,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.6", + "version": "0.18.8", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071" + "reference": "84737afa634e6a833fc4f8b0c967553234d3f215" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/893ccf06e183f8ece2aed8dbf14d64d6ba036071", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/84737afa634e6a833fc4f8b0c967553234d3f215", + "reference": "84737afa634e6a833fc4f8b0c967553234d3f215", "shasum": "" }, "require": { @@ -4402,9 +4403,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.6" + "source": "https://github.com/utopia-php/storage/tree/0.18.8" }, - "time": "2024-11-06T09:58:50+00:00" + "time": "2024-12-04T08:30:35+00:00" }, { "name": "utopia-php/swoole", @@ -4924,29 +4925,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" @@ -4954,7 +4953,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4965,9 +4964,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", @@ -5118,16 +5117,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.1", + "version": "v1.18.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", "shasum": "" }, "require": { @@ -5138,13 +5137,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", + "friendsofphp/php-cs-fixer": "^3.65.0", + "illuminate/view": "^10.48.24", + "larastan/larastan": "^2.9.11", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^1.17.0", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -5180,7 +5179,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-24T17:22:50+00:00" + "time": "2024-11-26T15:34:00+00:00" }, { "name": "matthiasmullie/minify", @@ -5799,16 +5798,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": { @@ -5857,9 +5856,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", @@ -5921,26 +5920,27 @@ }, { "name": "phpspec/prophecy", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87" + "reference": "a0165c648cab6a80311c74ffc708a07bb53ecc93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/67a759e7d8746d501c41536ba40cd9c0a07d6a87", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/a0165c648cab6a80311c74ffc708a07bb53ecc93", + "reference": "a0165c648cab6a80311c74ffc708a07bb53ecc93", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2 || ^2.0", - "php": "^7.2 || 8.0.* || 8.1.* || 8.2.* || 8.3.*", + "php": "^7.2 || 8.0.* || 8.1.* || 8.2.* || 8.3.* || 8.4.*", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0", "sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0 || ^6.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.40", "phpspec/phpspec": "^6.0 || ^7.0", "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0" @@ -5984,9 +5984,9 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.19.0" + "source": "https://github.com/phpspec/prophecy/tree/v1.20.0" }, - "time": "2024-02-29T11:52:51+00:00" + "time": "2024-11-19T13:12:41+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -7567,16 +7567,16 @@ }, { "name": "symfony/console", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", - "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "url": "https://api.github.com/repos/symfony/console/zipball/23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", "shasum": "" }, "require": { @@ -7640,7 +7640,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.8" + "source": "https://github.com/symfony/console/tree/v7.2.0" }, "funding": [ { @@ -7656,20 +7656,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { @@ -7706,7 +7706,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.6" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -7722,20 +7722,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { @@ -7770,7 +7770,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.6" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -7786,20 +7786,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { @@ -7837,7 +7837,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.6" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -7853,7 +7853,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7881,8 +7881,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7957,8 +7957,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8035,8 +8035,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8113,8 +8113,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8171,16 +8171,16 @@ }, { "name": "symfony/process", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", - "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", "shasum": "" }, "require": { @@ -8212,7 +8212,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.8" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -8228,20 +8228,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:23:19+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/string", - "version": "v7.1.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", - "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { @@ -8299,7 +8299,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.8" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -8315,7 +8315,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:21+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "textalk/websocket", @@ -8547,7 +8547,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 834c237cd5e5f1c03a46d256ae671c9392b95200 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Tue, 10 Dec 2024 15:18:21 +0200 Subject: [PATCH 099/340] handling map size --- src/Appwrite/Platform/Workers/Usage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index ce2cb3ff52..3f24210cea 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -18,7 +18,7 @@ class Usage extends Action private int $aggregationInterval = 20; private int $keys = 0; private const INFINITY_PERIOD = '_inf_'; - private const KEYS_THRESHOLD = 12000; + private const KEYS_THRESHOLD = 20000; public static function getName(): string { From d80731e7dbbd160f37dea6b1ad952928e8e9a9b2 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Dec 2024 19:14:10 +1300 Subject: [PATCH 100/340] Allow pushing SDK to new branches --- src/Appwrite/Platform/Tasks/SDKs.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index 6e37f270a4..126dcd7fb4 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -41,15 +41,15 @@ class SDKs extends Action $this ->desc('Generate Appwrite SDKs') ->param('platform', null, new Nullable(new Text(256)), 'Selected Platform', optional: true) - ->param('sdk', null, new Nullable(new Text(256)), 'Selected SDK', optional:true) - ->param('version', null, new Nullable(new Text(256)), 'Selected SDK', optional:true) + ->param('sdk', null, new Nullable(new Text(256)), 'Selected SDK', optional: true) + ->param('version', null, new Nullable(new Text(256)), 'Selected SDK', optional: true) ->param('git', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we use git push?', optional: true) - ->param('production', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to production?', optional:true) - ->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional:true) + ->param('production', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to production?', optional: true) + ->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional: true) ->callback([$this, 'action']); } - public function action(?string $selectedPlatform, ?string $selectedSDK, ?string $version, ?string $git, ?string $production, ?string $message) + public function action(?string $selectedPlatform, ?string $selectedSDK, ?string $version, ?string $git, ?string $production, ?string $message): void { $selectedPlatform ??= Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); $selectedSDK ??= \strtolower(Console::confirm('Choose SDK ("*" for all):')); @@ -275,9 +275,13 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \exec('rm -rf ' . $target . ' && \ mkdir -p ' . $target . ' && \ cd ' . $target . ' && \ - git init --initial-branch=' . $gitBranch . ' && \ + git init && \ git remote add origin ' . $gitUrl . ' && \ - git fetch origin ' . $gitBranch . ' && \ + git fetch origin && \ + git checkout main || git checkout -b main && \ + git pull origin main && \ + git checkout ' . $gitBranch . ' || git checkout -b ' . $gitBranch . ' && \ + git fetch origin ' . $gitBranch . ' || git push -u origin ' . $gitBranch . ' && \ git pull origin ' . $gitBranch . ' && \ rm -rf ' . $target . '/* && \ cp -r ' . $result . '/. ' . $target . '/ && \ From bb6da36b36582f70770bbdba481a4a3ffbcd6ab3 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Dec 2024 19:15:10 +1300 Subject: [PATCH 101/340] Update versions --- app/config/platforms.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index e54fb0a073..e83076cb9e 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -245,7 +245,7 @@ return [ [ 'key' => 'nodejs', 'name' => 'Node.js', - 'version' => '14.1.0', + 'version' => '14.2.0', 'url' => 'https://github.com/appwrite/sdk-for-node', 'package' => 'https://www.npmjs.com/package/node-appwrite', 'enabled' => true, @@ -263,7 +263,7 @@ return [ [ 'key' => 'deno', 'name' => 'Deno', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-deno', 'package' => 'https://deno.land/x/appwrite', 'enabled' => true, @@ -281,7 +281,7 @@ return [ [ 'key' => 'php', 'name' => 'PHP', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-php', 'package' => 'https://packagist.org/packages/appwrite/appwrite', 'enabled' => true, @@ -299,7 +299,7 @@ return [ [ 'key' => 'python', 'name' => 'Python', - 'version' => '6.1.0', + 'version' => '6.2.0', 'url' => 'https://github.com/appwrite/sdk-for-python', 'package' => 'https://pypi.org/project/appwrite/', 'enabled' => true, @@ -317,7 +317,7 @@ return [ [ 'key' => 'ruby', 'name' => 'Ruby', - 'version' => '12.1.1', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-ruby', 'package' => 'https://rubygems.org/gems/appwrite', 'enabled' => true, @@ -335,7 +335,7 @@ return [ [ 'key' => 'go', 'name' => 'Go', - 'version' => '0.2.0', + 'version' => '0.3.0', 'url' => 'https://github.com/appwrite/sdk-for-go', 'package' => 'https://github.com/appwrite/sdk-for-go', 'enabled' => true, @@ -353,7 +353,7 @@ return [ [ 'key' => 'dotnet', 'name' => '.NET', - 'version' => '0.10.1', + 'version' => '0.11.0', 'url' => 'https://github.com/appwrite/sdk-for-dotnet', 'package' => 'https://www.nuget.org/packages/Appwrite', 'enabled' => true, @@ -371,7 +371,7 @@ return [ [ 'key' => 'dart', 'name' => 'Dart', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-dart', 'package' => 'https://pub.dev/packages/dart_appwrite', 'enabled' => true, @@ -389,7 +389,7 @@ return [ [ 'key' => 'kotlin', 'name' => 'Kotlin', - 'version' => '6.1.0', + 'version' => '6.2.0', 'url' => 'https://github.com/appwrite/sdk-for-kotlin', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin', 'enabled' => true, @@ -411,7 +411,7 @@ return [ [ 'key' => 'swift', 'name' => 'Swift', - 'version' => '6.1.0', + 'version' => '6.2.0', 'url' => 'https://github.com/appwrite/sdk-for-swift', 'package' => 'https://github.com/appwrite/sdk-for-swift', 'enabled' => true, From 8531b70089cfee3c0c8aa36830b6ccd0519a44ce Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Dec 2024 19:15:29 +1300 Subject: [PATCH 102/340] Update docs --- .../examples/databases/update-string-attribute.md | 2 +- .../server-dart/examples/messaging/create-push.md | 9 ++++++--- .../server-dart/examples/messaging/update-push.md | 3 +++ .../examples/databases/update-string-attribute.md | 2 +- .../server-deno/examples/messaging/create-push.md | 13 ++++++++----- .../server-deno/examples/messaging/update-push.md | 7 +++++-- .../examples/databases/update-string-attribute.md | 2 +- .../server-dotnet/examples/messaging/create-push.md | 12 ++++++++---- .../server-dotnet/examples/messaging/update-push.md | 6 +++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-go/examples/messaging/create-push.md | 9 ++++++--- .../server-go/examples/messaging/update-push.md | 3 +++ .../1.6.x/server-graphql/examples/account/create.md | 1 + .../1.6.x/server-graphql/examples/account/get.md | 1 + .../server-graphql/examples/account/update-email.md | 1 + .../server-graphql/examples/account/update-m-f-a.md | 1 + .../examples/account/update-mfa-authenticator.md | 1 + .../server-graphql/examples/account/update-name.md | 1 + .../examples/account/update-password.md | 1 + .../server-graphql/examples/account/update-phone.md | 1 + .../server-graphql/examples/account/update-prefs.md | 1 + .../examples/account/update-status.md | 1 + .../examples/databases/create-boolean-attribute.md | 2 ++ .../examples/databases/create-collection.md | 2 ++ .../examples/databases/create-datetime-attribute.md | 2 ++ .../examples/databases/create-email-attribute.md | 2 ++ .../examples/databases/create-enum-attribute.md | 2 ++ .../examples/databases/create-float-attribute.md | 2 ++ .../examples/databases/create-index.md | 2 ++ .../examples/databases/create-integer-attribute.md | 2 ++ .../examples/databases/create-ip-attribute.md | 2 ++ .../databases/create-relationship-attribute.md | 2 ++ .../examples/databases/create-string-attribute.md | 2 ++ .../examples/databases/create-url-attribute.md | 2 ++ .../examples/databases/get-collection.md | 2 ++ .../server-graphql/examples/databases/get-index.md | 2 ++ .../examples/databases/list-collections.md | 2 ++ .../examples/databases/list-indexes.md | 2 ++ .../examples/databases/update-boolean-attribute.md | 2 ++ .../examples/databases/update-collection.md | 2 ++ .../examples/databases/update-datetime-attribute.md | 2 ++ .../examples/databases/update-email-attribute.md | 2 ++ .../examples/databases/update-enum-attribute.md | 2 ++ .../examples/databases/update-float-attribute.md | 2 ++ .../examples/databases/update-integer-attribute.md | 2 ++ .../examples/databases/update-ip-attribute.md | 2 ++ .../databases/update-relationship-attribute.md | 2 ++ .../examples/databases/update-string-attribute.md | 4 +++- .../examples/databases/update-url-attribute.md | 2 ++ .../examples/messaging/create-push.md | 7 +++++-- .../examples/messaging/create-subscriber.md | 1 + .../examples/messaging/get-subscriber.md | 1 + .../examples/messaging/list-subscribers.md | 1 + .../examples/messaging/list-targets.md | 1 + .../examples/messaging/update-push.md | 5 ++++- .../examples/users/create-argon2user.md | 1 + .../examples/users/create-bcrypt-user.md | 1 + .../examples/users/create-m-d5user.md | 1 + .../examples/users/create-p-h-pass-user.md | 1 + .../examples/users/create-s-h-a-user.md | 1 + .../examples/users/create-scrypt-modified-user.md | 1 + .../examples/users/create-scrypt-user.md | 1 + .../server-graphql/examples/users/create-target.md | 1 + .../1.6.x/server-graphql/examples/users/create.md | 1 + .../examples/users/delete-mfa-authenticator.md | 1 + .../server-graphql/examples/users/get-target.md | 1 + .../1.6.x/server-graphql/examples/users/get.md | 1 + .../server-graphql/examples/users/list-targets.md | 1 + .../1.6.x/server-graphql/examples/users/list.md | 1 + .../examples/users/update-email-verification.md | 1 + .../server-graphql/examples/users/update-email.md | 1 + .../server-graphql/examples/users/update-labels.md | 1 + .../server-graphql/examples/users/update-mfa.md | 1 + .../server-graphql/examples/users/update-name.md | 1 + .../examples/users/update-password.md | 1 + .../examples/users/update-phone-verification.md | 1 + .../server-graphql/examples/users/update-phone.md | 1 + .../server-graphql/examples/users/update-status.md | 1 + .../server-graphql/examples/users/update-target.md | 1 + .../java/databases/update-string-attribute.md | 2 +- .../server-kotlin/java/messaging/create-push.md | 9 ++++++--- .../server-kotlin/java/messaging/update-push.md | 3 +++ .../kotlin/databases/update-string-attribute.md | 2 +- .../server-kotlin/kotlin/messaging/create-push.md | 11 +++++++---- .../server-kotlin/kotlin/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-nodejs/examples/messaging/create-push.md | 11 +++++++---- .../server-nodejs/examples/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-php/examples/messaging/create-push.md | 11 +++++++---- .../server-php/examples/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-python/examples/messaging/create-push.md | 11 +++++++---- .../server-python/examples/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-rest/examples/messaging/create-push.md | 7 +++++-- .../server-rest/examples/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-ruby/examples/messaging/create-push.md | 11 +++++++---- .../server-ruby/examples/messaging/update-push.md | 5 ++++- .../examples/databases/update-string-attribute.md | 2 +- .../server-swift/examples/messaging/create-push.md | 12 ++++++++---- .../server-swift/examples/messaging/update-push.md | 6 +++++- 103 files changed, 244 insertions(+), 70 deletions(-) diff --git a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md index c2f3804c66..f9498aa36b 100644 --- a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ AttributeString result = await databases.updateStringAttribute( key: '', xrequired: false, xdefault: '<DEFAULT>', - size: 0, // (optional) + size: 1, // (optional) newKey: '', // (optional) ); diff --git a/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md b/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md index c3c7d2ffc5..e496de9d27 100644 --- a/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md @@ -9,8 +9,8 @@ Messaging messaging = Messaging(client); Message result = await messaging.createPush( messageId: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', // (optional) + body: '<BODY>', // (optional) topics: [], // (optional) users: [], // (optional) targets: [], // (optional) @@ -21,7 +21,10 @@ Message result = await messaging.createPush( sound: '<SOUND>', // (optional) color: '<COLOR>', // (optional) tag: '<TAG>', // (optional) - badge: '<BADGE>', // (optional) + badge: 0, // (optional) draft: false, // (optional) scheduledAt: '', // (optional) + contentAvailable: false, // (optional) + critical: false, // (optional) + priority: MessagePriority.normal, // (optional) ); diff --git a/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md b/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md index dcec9b243f..f5d75332e2 100644 --- a/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md @@ -24,4 +24,7 @@ Message result = await messaging.updatePush( badge: 0, // (optional) draft: false, // (optional) scheduledAt: '', // (optional) + contentAvailable: false, // (optional) + critical: false, // (optional) + priority: MessagePriority.normal, // (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md index 6603c377cb..d57f8fd663 100644 --- a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const response = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md b/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md index 005cca1b77..7b41911918 100644 --- a/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "https://deno.land/x/appwrite/mod.ts"; +import { Client, Messaging, MessagePriority } from "https://deno.land/x/appwrite/mod.ts"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -9,8 +9,8 @@ const messaging = new Messaging(client); const response = await messaging.createPush( '<MESSAGE_ID>', // messageId - '<TITLE>', // title - '<BODY>', // body + '<TITLE>', // title (optional) + '<BODY>', // body (optional) [], // topics (optional) [], // users (optional) [], // targets (optional) @@ -21,7 +21,10 @@ const response = await messaging.createPush( '<SOUND>', // sound (optional) '<COLOR>', // color (optional) '<TAG>', // tag (optional) - '<BADGE>', // badge (optional) + null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md b/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md index 9c66ab6ab7..11437fabe1 100644 --- a/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "https://deno.land/x/appwrite/mod.ts"; +import { Client, Messaging, MessagePriority } from "https://deno.land/x/appwrite/mod.ts"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -23,5 +23,8 @@ const response = await messaging.updatePush( '<TAG>', // tag (optional) null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md index e915d23f51..a180815a50 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ AttributeString result = await databases.UpdateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md b/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md index f83a0ed8df..588781b3a1 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -11,8 +12,8 @@ Messaging messaging = new Messaging(client); Message result = await messaging.CreatePush( messageId: "<MESSAGE_ID>", - title: "<TITLE>", - body: "<BODY>", + title: "<TITLE>", // optional + body: "<BODY>", // optional topics: new List<string>(), // optional users: new List<string>(), // optional targets: new List<string>(), // optional @@ -23,7 +24,10 @@ Message result = await messaging.CreatePush( sound: "<SOUND>", // optional color: "<COLOR>", // optional tag: "<TAG>", // optional - badge: "<BADGE>", // optional + badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority.Normal // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md b/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md index 0de09d570a..2b48d1827d 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -25,5 +26,8 @@ Message result = await messaging.UpdatePush( tag: "<TAG>", // optional badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority.Normal // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md index d662060f09..f3e6addb07 100644 --- a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md @@ -20,7 +20,7 @@ func main() { "", false, "<DEFAULT>", - databases.WithUpdateStringAttributeSize(0), + databases.WithUpdateStringAttributeSize(1), databases.WithUpdateStringAttributeNewKey(""), ) diff --git a/docs/examples/1.6.x/server-go/examples/messaging/create-push.md b/docs/examples/1.6.x/server-go/examples/messaging/create-push.md index 090e0cbca2..b40037472f 100644 --- a/docs/examples/1.6.x/server-go/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-go/examples/messaging/create-push.md @@ -16,8 +16,8 @@ func main() { service := messaging.NewMessaging(client) response, error := service.CreatePush( "<MESSAGE_ID>", - "<TITLE>", - "<BODY>", + messaging.WithCreatePushTitle("<TITLE>"), + messaging.WithCreatePushBody("<BODY>"), messaging.WithCreatePushTopics([]interface{}{}), messaging.WithCreatePushUsers([]interface{}{}), messaging.WithCreatePushTargets([]interface{}{}), @@ -28,9 +28,12 @@ func main() { messaging.WithCreatePushSound("<SOUND>"), messaging.WithCreatePushColor("<COLOR>"), messaging.WithCreatePushTag("<TAG>"), - messaging.WithCreatePushBadge("<BADGE>"), + messaging.WithCreatePushBadge(0), messaging.WithCreatePushDraft(false), messaging.WithCreatePushScheduledAt(""), + messaging.WithCreatePushContentAvailable(false), + messaging.WithCreatePushCritical(false), + messaging.WithCreatePushPriority("normal"), ) if error != nil { diff --git a/docs/examples/1.6.x/server-go/examples/messaging/update-push.md b/docs/examples/1.6.x/server-go/examples/messaging/update-push.md index af1b6095cd..d1b47256c0 100644 --- a/docs/examples/1.6.x/server-go/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-go/examples/messaging/update-push.md @@ -31,6 +31,9 @@ func main() { messaging.WithUpdatePushBadge(0), messaging.WithUpdatePushDraft(false), messaging.WithUpdatePushScheduledAt(""), + messaging.WithUpdatePushContentAvailable(false), + messaging.WithUpdatePushCritical(false), + messaging.WithUpdatePushPriority("normal"), ) if error != nil { diff --git a/docs/examples/1.6.x/server-graphql/examples/account/create.md b/docs/examples/1.6.x/server-graphql/examples/account/create.md index 3f8e3c3cf7..0d39394a3d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/create.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/get.md b/docs/examples/1.6.x/server-graphql/examples/account/get.md index e4db8f0e41..f4f07c187f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/get.md @@ -28,6 +28,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md index b207bad4bb..c879e24a43 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md index d2cd3d6ae5..787c2e0860 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md index c74062c7d4..9cfe9150be 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md index 850b5760a0..8ba2c99d9c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md index 5904da0842..f3619a10d2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md index 408a203300..adecb71168 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md index 40db7b43db..57280247e4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md index aca8c098e7..c17f556842 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md @@ -28,6 +28,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md index 6e969a587e..aa0bfa832e 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md index 05175cc1e7..51eb51f410 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md index fcd5cb37a2..47601df0d8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md index 1f23a23ba7..e5845ccd47 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md index 410a7983b4..d13c080e4a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md index ae6f9f72d6..2a270c3aff 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md index efc92a798c..2875a9b4b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md @@ -13,5 +13,7 @@ mutation { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md index 1dc43f6b0d..8c79706817 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md index b2fd7215a0..0f4ad9e139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md index ddca20b83a..f66b87d6af 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md index 3c290712e9..62d97d6962 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md index d2a39756c9..89ad873e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md index f76b71b6ba..ed27286b0d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md @@ -19,6 +19,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md index de3c44ebe0..29de7a76f8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md @@ -10,5 +10,7 @@ query { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md index b821b6c4cf..8dafbf7042 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md @@ -22,6 +22,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md index e1c11b6c03..3cb67c6451 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md @@ -12,6 +12,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md index e92b41a14e..d508e62139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md index fc78bb8efc..e918c058b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md index 46d9bbb728..a21b910edc 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md index e05d365162..6c83d80e16 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md index 619cbf817c..378e32f9b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md index 7641745a35..c5c7afca44 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md index 11b7a66014..e38ccaa88c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md index 649fa881b5..7a26224200 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md index 88ba2f9636..6694540d93 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md @@ -12,6 +12,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md index 4d88462efb..afafb307f5 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md @@ -5,7 +5,7 @@ mutation { key: "", required: false, default: "<DEFAULT>", - size: 0, + size: 1, newKey: "" ) { key @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md index 06838a9ed4..f9f14a04f6 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md b/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md index 3084c97635..92264d1b67 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md @@ -13,9 +13,12 @@ mutation { sound: "<SOUND>", color: "<COLOR>", tag: "<TAG>", - badge: "<BADGE>", + badge: 0, draft: false, - scheduledAt: "" + scheduledAt: "", + contentAvailable: false, + critical: false, + priority: "normal" ) { _id _createdAt diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md index b2712ebb48..bab53612b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md @@ -17,6 +17,7 @@ mutation { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md index 54096dd70a..2e1672d010 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md @@ -16,6 +16,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md index 5c48ae34bb..a5a4f91e56 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md @@ -19,6 +19,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md index 8e356dce5f..aa82276de2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md b/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md index 9039792573..8ee2f57610 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md @@ -15,7 +15,10 @@ mutation { tag: "<TAG>", badge: 0, draft: false, - scheduledAt: "" + scheduledAt: "", + contentAvailable: false, + critical: false, + priority: "normal" ) { _id _createdAt diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md index 464dc754c9..7f99622e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md index 4d4bb09194..26659176eb 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md index e8e833e6de..7e642b8233 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md index 53960e7890..4c06b007a2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md index 17e287f8b3..f99da2752d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md index 6d51fb29ba..624ffcdd38 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md @@ -36,6 +36,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md index 0d4bac1db8..68a5f4c75f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md @@ -38,6 +38,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md index a3a0696dec..7068c21aba 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md @@ -15,5 +15,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create.md b/docs/examples/1.6.x/server-graphql/examples/users/create.md index 826a5168ef..465da80432 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md index 227c340c68..26c9594a53 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md index e4ba1a04a1..c84f947898 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md @@ -11,5 +11,6 @@ query { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get.md b/docs/examples/1.6.x/server-graphql/examples/users/get.md index f94a5818ed..9d0be685d9 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get.md @@ -30,6 +30,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md index 05e796f167..408fd96f80 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list.md b/docs/examples/1.6.x/server-graphql/examples/users/list.md index e2326dd1a2..a90121adf2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list.md @@ -33,6 +33,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md index 6bb2781854..cda7278ac0 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md index 046937ac04..408a74972b 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md index 93da33d805..cb3c5b6483 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md index 9219aa1aea..ac09ea19a4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md index 01a53ce479..ec7e3dc27c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md index c95637c4ce..95ef74c83d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md index 58343ae365..c6afa54ba4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md index dbcb076c65..d3fc7d5f37 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md index ad05bc75ff..2499c1c258 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md index fe3444ede7..1f7cc1147a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md @@ -14,5 +14,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md index 75be9e01f8..2d69006181 100644 --- a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md @@ -15,7 +15,7 @@ databases.updateStringAttribute( "", // key false, // required "<DEFAULT>", // default - 0, // size (optional) + 1, // size (optional) "", // newKey (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md b/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md index 934f1faaa8..56c7a60795 100644 --- a/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md +++ b/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md @@ -11,8 +11,8 @@ Messaging messaging = new Messaging(client); messaging.createPush( "<MESSAGE_ID>", // messageId - "<TITLE>", // title - "<BODY>", // body + "<TITLE>", // title (optional) + "<BODY>", // body (optional) listOf(), // topics (optional) listOf(), // users (optional) listOf(), // targets (optional) @@ -23,9 +23,12 @@ messaging.createPush( "<SOUND>", // sound (optional) "<COLOR>", // color (optional) "<TAG>", // tag (optional) - "<BADGE>", // badge (optional) + 0, // badge (optional) false, // draft (optional) "", // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.NORMAL, // priority (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md b/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md index ef04203c37..bb8c3c8c2e 100644 --- a/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md +++ b/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md @@ -26,6 +26,9 @@ messaging.updatePush( 0, // badge (optional) false, // draft (optional) "", // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.NORMAL, // priority (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md index a37d4566ee..32e17beb9c 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md @@ -15,6 +15,6 @@ val response = databases.updateStringAttribute( key = "", required = false, default = "<DEFAULT>", - size = 0, // optional + size = 1, // optional newKey = "" // optional ) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md index 6a95f63992..f92a49d627 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md @@ -11,8 +11,8 @@ val messaging = Messaging(client) val response = messaging.createPush( messageId = "<MESSAGE_ID>", - title = "<TITLE>", - body = "<BODY>", + title = "<TITLE>", // optional + body = "<BODY>", // optional topics = listOf(), // optional users = listOf(), // optional targets = listOf(), // optional @@ -23,7 +23,10 @@ val response = messaging.createPush( sound = "<SOUND>", // optional color = "<COLOR>", // optional tag = "<TAG>", // optional - badge = "<BADGE>", // optional + badge = 0, // optional draft = false, // optional - scheduledAt = "" // optional + scheduledAt = "", // optional + contentAvailable = false, // optional + critical = false, // optional + priority = "normal" // optional ) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md index d91694e1bc..0ba72c461c 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md @@ -25,5 +25,8 @@ val response = messaging.updatePush( tag = "<TAG>", // optional badge = 0, // optional draft = false, // optional - scheduledAt = "" // optional + scheduledAt = "", // optional + contentAvailable = false, // optional + critical = false, // optional + priority = "normal" // optional ) diff --git a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md index f379fdc0cf..6aecbb591e 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const result = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md b/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md index 54103e11f7..bb98538748 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md @@ -9,8 +9,8 @@ const messaging = new sdk.Messaging(client); const result = await messaging.createPush( '<MESSAGE_ID>', // messageId - '<TITLE>', // title - '<BODY>', // body + '<TITLE>', // title (optional) + '<BODY>', // body (optional) [], // topics (optional) [], // users (optional) [], // targets (optional) @@ -21,7 +21,10 @@ const result = await messaging.createPush( '<SOUND>', // sound (optional) '<COLOR>', // color (optional) '<TAG>', // tag (optional) - '<BADGE>', // badge (optional) + null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + sdk.MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md b/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md index ec87ecf7cf..700c3a99de 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md @@ -23,5 +23,8 @@ const result = await messaging.updatePush( '<TAG>', // tag (optional) null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + sdk.MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md index 9e821e4436..721ba324de 100644 --- a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md @@ -16,6 +16,6 @@ $result = $databases->updateStringAttribute( key: '', required: false, default: '<DEFAULT>', - size: null, // optional + size: 1, // optional newKey: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/messaging/create-push.md b/docs/examples/1.6.x/server-php/examples/messaging/create-push.md index 7838576df0..9aaf6ad4ad 100644 --- a/docs/examples/1.6.x/server-php/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-php/examples/messaging/create-push.md @@ -12,8 +12,8 @@ $messaging = new Messaging($client); $result = $messaging->createPush( messageId: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', // optional + body: '<BODY>', // optional topics: [], // optional users: [], // optional targets: [], // optional @@ -24,7 +24,10 @@ $result = $messaging->createPush( sound: '<SOUND>', // optional color: '<COLOR>', // optional tag: '<TAG>', // optional - badge: '<BADGE>', // optional + badge: null, // optional draft: false, // optional - scheduledAt: '' // optional + scheduledAt: '', // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority::NORMAL() // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/messaging/update-push.md b/docs/examples/1.6.x/server-php/examples/messaging/update-push.md index 09a4d96042..7546fc8668 100644 --- a/docs/examples/1.6.x/server-php/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-php/examples/messaging/update-push.md @@ -26,5 +26,8 @@ $result = $messaging->updatePush( tag: '<TAG>', // optional badge: null, // optional draft: false, // optional - scheduledAt: '' // optional + scheduledAt: '', // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority::NORMAL() // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md index bbe7ddb19f..ab910d9800 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ result = databases.update_string_attribute( key = '', required = False, default = '<DEFAULT>', - size = None, # optional + size = 1, # optional new_key = '' # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md index ffed825a3d..616b945d33 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md @@ -9,8 +9,8 @@ messaging = Messaging(client) result = messaging.create_push( message_id = '<MESSAGE_ID>', - title = '<TITLE>', - body = '<BODY>', + title = '<TITLE>', # optional + body = '<BODY>', # optional topics = [], # optional users = [], # optional targets = [], # optional @@ -21,7 +21,10 @@ result = messaging.create_push( sound = '<SOUND>', # optional color = '<COLOR>', # optional tag = '<TAG>', # optional - badge = '<BADGE>', # optional + badge = None, # optional draft = False, # optional - scheduled_at = '' # optional + scheduled_at = '', # optional + content_available = False, # optional + critical = False, # optional + priority = MessagePriority.NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md index 3c3965c3bd..f5bdf155e6 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md @@ -23,5 +23,8 @@ result = messaging.update_push( tag = '<TAG>', # optional badge = None, # optional draft = False, # optional - scheduled_at = '' # optional + scheduled_at = '', # optional + content_available = False, # optional + critical = False, # optional + priority = MessagePriority.NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md index 197ea2767d..71a5302e1a 100644 --- a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md @@ -8,6 +8,6 @@ X-Appwrite-Key: <YOUR_API_KEY> { "required": false, "default": "<DEFAULT>", - "size": 0, + "size": 1, "newKey": } diff --git a/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md b/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md index 1c7550950b..cf5256d921 100644 --- a/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md @@ -19,7 +19,10 @@ X-Appwrite-Key: <YOUR_API_KEY> "sound": "<SOUND>", "color": "<COLOR>", "tag": "<TAG>", - "badge": "<BADGE>", + "badge": 0, "draft": false, - "scheduledAt": + "scheduledAt": , + "contentAvailable": false, + "critical": false, + "priority": "normal" } diff --git a/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md b/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md index 7a0338c74b..2159bc8aa2 100644 --- a/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md @@ -20,5 +20,8 @@ X-Appwrite-Key: <YOUR_API_KEY> "tag": "<TAG>", "badge": 0, "draft": false, - "scheduledAt": + "scheduledAt": , + "contentAvailable": false, + "critical": false, + "priority": "normal" } diff --git a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md index 3b3c5eb644..5e4ac573dc 100644 --- a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ result = databases.update_string_attribute( key: '', required: false, default: '<DEFAULT>', - size: null, # optional + size: 1, # optional new_key: '' # optional ) diff --git a/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md b/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md index 1c6700db43..61663f4dc0 100644 --- a/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md @@ -11,8 +11,8 @@ messaging = Messaging.new(client) result = messaging.create_push( message_id: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', # optional + body: '<BODY>', # optional topics: [], # optional users: [], # optional targets: [], # optional @@ -23,7 +23,10 @@ result = messaging.create_push( sound: '<SOUND>', # optional color: '<COLOR>', # optional tag: '<TAG>', # optional - badge: '<BADGE>', # optional + badge: null, # optional draft: false, # optional - scheduled_at: '' # optional + scheduled_at: '', # optional + content_available: false, # optional + critical: false, # optional + priority: MessagePriority::NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md b/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md index 54f6368eee..6bf9fcaa79 100644 --- a/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md @@ -25,5 +25,8 @@ result = messaging.update_push( tag: '<TAG>', # optional badge: null, # optional draft: false, # optional - scheduled_at: '' # optional + scheduled_at: '', # optional + content_available: false, # optional + critical: false, # optional + priority: MessagePriority::NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md index 5fafd5e72e..d3129dcce2 100644 --- a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md @@ -13,7 +13,7 @@ let attributeString = try await databases.updateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md b/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md index dbc7bf0ca6..42f48ddd2e 100644 --- a/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint @@ -9,8 +10,8 @@ let messaging = Messaging(client) let message = try await messaging.createPush( messageId: "<MESSAGE_ID>", - title: "<TITLE>", - body: "<BODY>", + title: "<TITLE>", // optional + body: "<BODY>", // optional topics: [], // optional users: [], // optional targets: [], // optional @@ -21,8 +22,11 @@ let message = try await messaging.createPush( sound: "<SOUND>", // optional color: "<COLOR>", // optional tag: "<TAG>", // optional - badge: "<BADGE>", // optional + badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: .normal // optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md b/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md index 40ce34bf66..02893a180a 100644 --- a/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint @@ -23,6 +24,9 @@ let message = try await messaging.updatePush( tag: "<TAG>", // optional badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: .normal // optional ) From 071f050aaf1113ae64604bb81732ab20b3c6f456 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 11 Dec 2024 12:57:25 +0200 Subject: [PATCH 103/340] Add throwable migration error --- src/Appwrite/Platform/Workers/Migrations.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index fdd885effa..4d67b39031 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -355,6 +355,12 @@ class Migrations extends Action $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); + call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + ]); + return; } @@ -388,18 +394,22 @@ class Migrations extends Action $source->error(); foreach ($source->getErrors() as $error) { + /** @var MigrationException $error */ call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ - 'migrationId' => $migration->getId() ?? '', + 'migrationId' => $migration->getId(), 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', 'resourceName' => $error->getResourceName(), 'resourceGroup' => $error->getResourceGroup() ]); } foreach ($destination->getErrors() as $error) { + /** @var MigrationException $error */ call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ - 'migrationId' => $migration->getId() ?? '', + 'migrationId' => $migration->getId(), 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', 'resourceName' => $error->getResourceName(), 'resourceGroup' => $error->getResourceGroup() ]); From 142782825daa3b250986b66a6d506a2112d682fa Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 11 Dec 2024 13:31:17 +0200 Subject: [PATCH 104/340] Add throwable migration error --- src/Appwrite/Platform/Workers/Migrations.php | 49 +++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 4d67b39031..cd695d09d7 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -390,35 +390,40 @@ class Migrations extends Action if ($migration->getAttribute('status', '') === 'failed') { Console::error('Migration('.$migration->getInternalId().':'.$migration->getId().') failed, Project('.$this->project->getInternalId().':'.$this->project->getId().')'); - $destination->error(); - $source->error(); + if ($destination) { + $destination->error(); - foreach ($source->getErrors() as $error) { - /** @var MigrationException $error */ - call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ - 'migrationId' => $migration->getId(), - 'source' => $migration->getAttribute('source') ?? '', - 'destination' => $migration->getAttribute('destination') ?? '', - 'resourceName' => $error->getResourceName(), - 'resourceGroup' => $error->getResourceGroup() - ]); + foreach ($destination->getErrors() as $error) { + /** @var MigrationException $error */ + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); + } } - foreach ($destination->getErrors() as $error) { - /** @var MigrationException $error */ - call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ - 'migrationId' => $migration->getId(), - 'source' => $migration->getAttribute('source') ?? '', - 'destination' => $migration->getAttribute('destination') ?? '', - 'resourceName' => $error->getResourceName(), - 'resourceGroup' => $error->getResourceGroup() - ]); + if ($source) { + $source->error(); + + foreach ($source->getErrors() as $error) { + /** @var MigrationException $error */ + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); + } } } if ($migration->getAttribute('status', '') === 'completed') { - $destination->success(); - $source->success(); + $destination?->success(); + $source?->success(); } } } From 66c5f959c0e43753029f8c1d5cfec836054e84ed Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 11 Dec 2024 16:34:13 +0200 Subject: [PATCH 105/340] Sentry Console::error --- src/Appwrite/Platform/Workers/Migrations.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index cd695d09d7..3bbaecaaec 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -355,6 +355,8 @@ class Migrations extends Action $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); + Console::error('Sentry error: '.$th->getMessage()); + call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [ 'migrationId' => $migration->getId(), 'source' => $migration->getAttribute('source') ?? '', From 4984abb0ddacb012455d1e529c8cf1a5d789de3b Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 11 Dec 2024 16:58:00 +0200 Subject: [PATCH 106/340] tests nulls --- src/Appwrite/Platform/Workers/Migrations.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 3bbaecaaec..5647c3800e 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -351,6 +351,10 @@ class Migrations extends Action Console::error($th->getMessage()); Console::error($th->getTraceAsString()); + var_dump($transfer); + var_dump($destination); + var_dump($destination); + if (! $migration->isEmpty()) { $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); From 17b5b3cf4b8999c390f396a15d29654812ebeff9 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 11 Dec 2024 17:06:19 +0200 Subject: [PATCH 107/340] Remove comments --- src/Appwrite/Platform/Workers/Migrations.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 5647c3800e..cd695d09d7 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -351,16 +351,10 @@ class Migrations extends Action Console::error($th->getMessage()); Console::error($th->getTraceAsString()); - var_dump($transfer); - var_dump($destination); - var_dump($destination); - if (! $migration->isEmpty()) { $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); - Console::error('Sentry error: '.$th->getMessage()); - call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [ 'migrationId' => $migration->getId(), 'source' => $migration->getAttribute('source') ?? '', From 75b42e134ac38b41f03d16078315875da878e20c Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 12 Dec 2024 14:30:26 +0400 Subject: [PATCH 108/340] chore: replace occurrences of dbForConsole to dbForPlatform --- app/cli.php | 18 +- app/controllers/api/avatars.php | 30 +- app/controllers/api/functions.php | 82 ++-- app/controllers/api/messaging.php | 54 +-- app/controllers/api/migrations.php | 56 +-- app/controllers/api/project.php | 8 +- app/controllers/api/projects.php | 408 +++++++++--------- app/controllers/api/proxy.php | 48 +-- app/controllers/api/vcs.php | 128 +++--- app/controllers/general.php | 52 +-- app/controllers/mock.php | 18 +- app/controllers/shared/api.php | 16 +- app/http.php | 34 +- app/init.php | 48 +-- app/worker.php | 22 +- src/Appwrite/Platform/Tasks/Maintenance.php | 20 +- src/Appwrite/Platform/Tasks/Migrate.php | 20 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 24 +- .../Platform/Tasks/ScheduleExecutions.php | 8 +- .../Platform/Tasks/ScheduleFunctions.php | 2 +- .../Platform/Tasks/ScheduleMessages.php | 6 +- src/Appwrite/Platform/Tasks/Specs.php | 2 +- src/Appwrite/Platform/Workers/Builds.php | 36 +- .../Platform/Workers/Certificates.php | 42 +- src/Appwrite/Platform/Workers/Databases.php | 42 +- src/Appwrite/Platform/Workers/Deletes.php | 108 ++--- src/Appwrite/Platform/Workers/Migrations.php | 18 +- src/Appwrite/Platform/Workers/Webhooks.php | 36 +- 28 files changed, 693 insertions(+), 693 deletions(-) diff --git a/app/cli.php b/app/cli.php index fd49d2fed4..47f4525f0b 100644 --- a/app/cli.php +++ b/app/cli.php @@ -52,7 +52,7 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForConsole', function ($pools, $cache) { +CLI::setResource('dbForPlatform', function ($pools, $cache) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -67,9 +67,9 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { ->pop() ->getResource(); - $dbForConsole = new Database($dbAdapter, $cache); + $dbForPlatform = new Database($dbAdapter, $cache); - $dbForConsole + $dbForPlatform ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -78,7 +78,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { $collections = Config::getParam('collections', [])['console']; $last = \array_key_last($collections); - if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */ + if (!($dbForPlatform->exists($dbForPlatform->getDatabase(), $last))) { /** TODO cache ready variable using registry */ throw new Exception('Tables not ready yet.'); } @@ -94,15 +94,15 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { throw new Exception("Console is not ready yet. Please try again later."); } - return $dbForConsole; + return $dbForPlatform; }, ['pools', 'cache']); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -158,7 +158,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $database; }; -}, ['pools', 'dbForConsole', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); CLI::setResource('queue', function (Group $pools) { return $pools->get('queue')->pop()->getResource(); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index dadd9da5e3..f73f8a148a 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -61,9 +61,9 @@ $avatarCallback = function (string $type, string $code, int $width, int $height, unset($image); }; -$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForConsole, ?Logger $logger) { +$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger) { try { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -122,7 +122,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); @@ -565,14 +565,14 @@ App::get('/v1/cards/cloud') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -583,7 +583,7 @@ App::get('/v1/cards/cloud') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; @@ -772,14 +772,14 @@ App::get('/v1/cards/cloud-back') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -789,7 +789,7 @@ App::get('/v1/cards/cloud-back') $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); @@ -850,14 +850,14 @@ App::get('/v1/cards/cloud-og') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -872,7 +872,7 @@ App::get('/v1/cards/cloud-og') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index e38dba3f19..003efbad03 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -182,9 +182,9 @@ App::post('/v1/functions') ->inject('user') ->inject('queueForEvents') ->inject('queueForBuilds') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); @@ -207,7 +207,7 @@ App::post('/v1/functions') ->setAttribute('version', $templateVersion); } - $installation = $dbForConsole->getDocument('installations', $installationId); + $installation = $dbForPlatform->getDocument('installations', $installationId); if (!empty($installationId) && $installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -249,7 +249,7 @@ App::post('/v1/functions') ])); $schedule = Authorization::skip( - fn () => $dbForConsole->createDocument('schedules', new Document([ + fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region 'resourceType' => 'function', 'resourceId' => $function->getId(), @@ -268,7 +268,7 @@ App::post('/v1/functions') if (!empty($providerRepositoryId)) { $teamId = $project->getAttribute('teamId', ''); - $repository = $dbForConsole->createDocument('repositories', new Document([ + $repository = $dbForPlatform->createDocument('repositories', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -332,7 +332,7 @@ App::post('/v1/functions') $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); $rule = Authorization::skip( - fn () => $dbForConsole->createDocument('rules', new Document([ + fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), 'projectInternalId' => $project->getInternalId(), @@ -804,9 +804,9 @@ App::put('/v1/functions/:functionId') ->inject('project') ->inject('queueForEvents') ->inject('queueForBuilds') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { // TODO: If only branch changes, re-deploy $function = $dbForProject->getDocument('functions', $functionId); @@ -814,7 +814,7 @@ App::put('/v1/functions/:functionId') throw new Exception(Exception::FUNCTION_NOT_FOUND); } - $installation = $dbForConsole->getDocument('installations', $installationId); + $installation = $dbForPlatform->getDocument('installations', $installationId); if (!empty($installationId) && $installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -845,7 +845,7 @@ App::put('/v1/functions/:functionId') // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { - $repositories = $dbForConsole->find('repositories', [ + $repositories = $dbForPlatform->find('repositories', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', ['function']), @@ -853,7 +853,7 @@ App::put('/v1/functions/:functionId') ]); foreach ($repositories as $repository) { - $dbForConsole->deleteDocument('repositories', $repository->getId()); + $dbForPlatform->deleteDocument('repositories', $repository->getId()); } $providerRepositoryId = ''; @@ -869,7 +869,7 @@ App::put('/v1/functions/:functionId') if (!$isConnected && !empty($providerRepositoryId)) { $teamId = $project->getAttribute('teamId', ''); - $repository = $dbForConsole->createDocument('repositories', new Document([ + $repository = $dbForPlatform->createDocument('repositories', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -951,12 +951,12 @@ App::put('/v1/functions/:functionId') } // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents->setParam('functionId', $function->getId()); @@ -1069,8 +1069,8 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('dbForConsole') - ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForPlatform) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -1098,12 +1098,12 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ]))); // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForEvents ->setParam('functionId', $function->getId()) @@ -1131,8 +1131,8 @@ App::delete('/v1/functions/:functionId') ->inject('dbForProject') ->inject('queueForDeletes') ->inject('queueForEvents') - ->inject('dbForConsole') - ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Database $dbForPlatform) { $function = $dbForProject->getDocument('functions', $functionId); @@ -1145,11 +1145,11 @@ App::delete('/v1/functions/:functionId') } // Inform scheduler to no longer run function - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) @@ -1759,13 +1759,13 @@ App::post('/v1/functions/:functionId/executions') ->inject('request') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('user') ->inject('queueForEvents') ->inject('queueForUsage') ->inject('queueForFunctions') ->inject('geodb') - ->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForConsole, Document $user, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb) { + ->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForPlatform, Document $user, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb) { $async = \strval($async) === 'true' || \strval($async) === '1'; if (!$async && !is_null($scheduledAt)) { @@ -1956,7 +1956,7 @@ App::post('/v1/functions/:functionId/executions') 'userId' => $user->getId() ]; - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => ScheduleExecutions::getSupportedResource(), 'resourceId' => $execution->getId(), @@ -2291,9 +2291,9 @@ App::delete('/v1/functions/:functionId/executions/:executionId') ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, Database $dbForConsole, Event $queueForEvents) { + ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, Database $dbForPlatform, Event $queueForEvents) { $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -2319,7 +2319,7 @@ App::delete('/v1/functions/:functionId/executions/:executionId') } if ($status === 'scheduled') { - $schedule = $dbForConsole->findOne('schedules', [ + $schedule = $dbForPlatform->findOne('schedules', [ Query::equal('resourceId', [$execution->getId()]), Query::equal('resourceType', [ScheduleExecutions::getSupportedResource()]), Query::equal('active', [true]), @@ -2330,7 +2330,7 @@ App::delete('/v1/functions/:functionId/executions/:executionId') ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } @@ -2363,8 +2363,8 @@ App::post('/v1/functions/:functionId/variables') ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject, Database $dbForPlatform) { $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -2397,12 +2397,12 @@ App::post('/v1/functions/:functionId/variables') $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -2497,8 +2497,8 @@ App::put('/v1/functions/:functionId/variables/:variableId') ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForPlatform) { $function = $dbForProject->getDocument('functions', $functionId); @@ -2529,12 +2529,12 @@ App::put('/v1/functions/:functionId/variables/:variableId') $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->dynamic($variable, Response::MODEL_VARIABLE); }); @@ -2556,8 +2556,8 @@ App::delete('/v1/functions/:functionId/variables/:variableId') ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForPlatform) { $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -2578,12 +2578,12 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $response->noContent(); }); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e4a627d027..00a68454ee 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2649,11 +2649,11 @@ App::post('/v1/messaging/messages/email') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, array $attachments, bool $draft, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, array $attachments, bool $draft, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -2742,7 +2742,7 @@ App::post('/v1/messaging/messages/email') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -2797,11 +2797,11 @@ App::post('/v1/messaging/messages/sms') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $content, array $topics, array $users, array $targets, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $content, array $topics, array $users, array $targets, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -2859,7 +2859,7 @@ App::post('/v1/messaging/messages/sms') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -2923,11 +2923,11 @@ App::post('/v1/messaging/messages/push') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -3036,7 +3036,7 @@ App::post('/v1/messaging/messages/push') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -3339,11 +3339,11 @@ App::patch('/v1/messaging/messages/email/:messageId') ->param('attachments', null, new ArrayList(new CompoundUID()), 'Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $content, ?bool $draft, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, ?array $attachments, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $content, ?bool $draft, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, ?array $attachments, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3395,7 +3395,7 @@ App::patch('/v1/messaging/messages/email/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -3410,7 +3410,7 @@ App::patch('/v1/messaging/messages/email/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3425,7 +3425,7 @@ App::patch('/v1/messaging/messages/email/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3535,11 +3535,11 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $content, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $content, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3591,7 +3591,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -3606,7 +3606,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3621,7 +3621,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3700,11 +3700,11 @@ App::patch('/v1/messaging/messages/push/:messageId') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3756,7 +3756,7 @@ App::patch('/v1/messaging/messages/push/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForPlatform->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => 'message', 'resourceId' => $message->getId(), @@ -3771,7 +3771,7 @@ App::patch('/v1/messaging/messages/push/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3786,7 +3786,7 @@ App::patch('/v1/messaging/messages/push/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3923,10 +3923,10 @@ App::delete('/v1/messaging/messages/:messageId') ->label('sdk.response.model', Response::MODEL_NONE) ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') ->inject('response') - ->action(function (string $messageId, Database $dbForProject, Database $dbForConsole, Event $queueForEvents, Response $response) { + ->action(function (string $messageId, Database $dbForProject, Database $dbForPlatform, Event $queueForEvents, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3949,7 +3949,7 @@ App::delete('/v1/messaging/messages/:messageId') if (!empty($scheduleId)) { try { - $dbForConsole->deleteDocument('schedules', $scheduleId); + $dbForPlatform->deleteDocument('schedules', $scheduleId); } catch (Exception) { // Ignore } diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index bebb6ebaea..3abd1db016 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -104,20 +104,20 @@ App::post('/v1/migrations/firebase/oauth') ->param('projectId', '', new Text(65536), 'Project ID of the Firebase Project') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('user') ->inject('queueForEvents') ->inject('queueForMigrations') ->inject('request') - ->action(function (array $resources, string $projectId, Response $response, Database $dbForProject, Database $dbForConsole, Document $project, Document $user, Event $queueForEvents, Migration $queueForMigrations, Request $request) { + ->action(function (array $resources, string $projectId, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Document $user, Event $queueForEvents, Migration $queueForMigrations, Request $request) { $firebase = new OAuth2Firebase( System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['firebase']), Query::equal('userInternalId', [$user->getInternalId()]), ]); @@ -147,7 +147,7 @@ App::post('/v1/migrations/firebase/oauth') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } if ($identity->getAttribute('secrets')) { @@ -158,7 +158,7 @@ App::post('/v1/migrations/firebase/oauth') $identity = $identity ->setAttribute('secrets', json_encode($serviceAccount)); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } $migration = $dbForProject->createDocument('migrations', new Document([ @@ -563,15 +563,15 @@ App::get('/v1/migrations/firebase/report/oauth') ->inject('response') ->inject('request') ->inject('user') - ->inject('dbForConsole') - ->action(function (array $resources, string $projectId, Response $response, Request $request, Document $user, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $resources, string $projectId, Response $response, Request $request, Document $user, Database $dbForPlatform) { $firebase = new OAuth2Firebase( System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['firebase']), Query::equal('userInternalId', [$user->getInternalId()]), ]); @@ -610,7 +610,7 @@ App::get('/v1/migrations/firebase/report/oauth') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } // Get Service Account @@ -622,7 +622,7 @@ App::get('/v1/migrations/firebase/report/oauth') $identity = $identity ->setAttribute('secrets', json_encode($serviceAccount)); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } $firebase = new Firebase($serviceAccount); @@ -655,8 +655,8 @@ App::get('/v1/migrations/firebase/connect') ->inject('response') ->inject('request') ->inject('user') - ->inject('dbForConsole') - ->action(function (string $redirect, string $projectId, Response $response, Request $request, Document $user, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $redirect, string $projectId, Response $response, Request $request, Document $user, Database $dbForPlatform) { $state = \json_encode([ 'projectId' => $projectId, 'redirect' => $redirect, @@ -665,7 +665,7 @@ App::get('/v1/migrations/firebase/connect') $prefs = $user->getAttribute('prefs', []); $prefs['migrationState'] = $state; $user->setAttribute('prefs', $prefs); - $dbForConsole->updateDocument('users', $user->getId(), $user); + $dbForPlatform->updateDocument('users', $user->getId(), $user); $oauth2 = new OAuth2Firebase( System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), @@ -690,12 +690,12 @@ App::get('/v1/migrations/firebase/redirect') ->inject('project') ->inject('request') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $code, Document $user, Document $project, Request $request, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $code, Document $user, Document $project, Request $request, Response $response, Database $dbForPlatform) { $state = $user['prefs']['migrationState'] ?? '{}'; $prefs['migrationState'] = ''; $user->setAttribute('prefs', $prefs); - $dbForConsole->updateDocument('users', $user->getId(), $user); + $dbForPlatform->updateDocument('users', $user->getId(), $user); if (empty($state)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Installation requests from organisation members for the Appwrite Google App are currently unsupported.'); @@ -705,7 +705,7 @@ App::get('/v1/migrations/firebase/redirect') $redirect = $state['redirect'] ?? ''; $projectId = $state['projectId'] ?? ''; - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if (empty($redirect)) { $redirect = $request->getProtocol() . '://' . $request->getHostname() . '/console/project-$projectId/settings/migrations'; @@ -747,7 +747,7 @@ App::get('/v1/migrations/firebase/redirect') } // Makes sure this email is not already used in another identity - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); @@ -763,9 +763,9 @@ App::get('/v1/migrations/firebase/redirect') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } else { - $identity = $dbForConsole->createDocument('identities', new Document([ + $identity = $dbForPlatform->createDocument('identities', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::any()), @@ -806,16 +806,16 @@ App::get('/v1/migrations/firebase/projects') ->inject('user') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('request') - ->action(function (Document $user, Response $response, Document $project, Database $dbForConsole, Request $request) { + ->action(function (Document $user, Response $response, Document $project, Database $dbForPlatform, Request $request) { $firebase = new OAuth2Firebase( System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' ); - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['firebase']), Query::equal('userInternalId', [$user->getInternalId()]), ]); @@ -859,7 +859,7 @@ App::get('/v1/migrations/firebase/projects') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } $projects = $firebase->getProjects($accessToken); @@ -893,9 +893,9 @@ App::get('/v1/migrations/firebase/deauthorize') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->inject('user') ->inject('response') - ->inject('dbForConsole') - ->action(function (Document $user, Response $response, Database $dbForConsole) { - $identity = $dbForConsole->findOne('identities', [ + ->inject('dbForPlatform') + ->action(function (Document $user, Response $response, Database $dbForPlatform) { + $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['firebase']), Query::equal('userInternalId', [$user->getInternalId()]), ]); @@ -904,7 +904,7 @@ App::get('/v1/migrations/firebase/deauthorize') throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND } - $dbForConsole->deleteDocument('identities', $identity->getId()); + $dbForPlatform->deleteDocument('identities', $identity->getId()); $response->noContent(); }); diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 6053326308..45c8f2c32b 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -325,8 +325,8 @@ App::post('/v1/project/variables') ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $key, string $value, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $key, string $value, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) { $variableId = ID::unique(); $variable = new Document([ @@ -429,8 +429,8 @@ App::put('/v1/project/variables/:variableId') ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) { $variable = $dbForProject->getDocument('variables', $variableId); if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceType') !== 'project') { throw new Exception(Exception::VARIABLE_NOT_FOUND); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 92d3103293..388c9e22ea 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -83,13 +83,13 @@ App::post('/v1/projects') ->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true) ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('cache') ->inject('pools') ->inject('hooks') - ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForConsole, Cache $cache, Group $pools, Hooks $hooks) { + ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForPlatform, Cache $cache, Group $pools, Hooks $hooks) { - $team = $dbForConsole->getDocument('teams', $teamId); + $team = $dbForPlatform->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -151,7 +151,7 @@ App::post('/v1/projects') } try { - $project = $dbForConsole->createDocument('projects', new Document([ + $project = $dbForPlatform->createDocument('projects', new Document([ '$id' => $projectId, '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -308,8 +308,8 @@ App::get('/v1/projects') ->param('queries', [], new Projects(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); @@ -337,7 +337,7 @@ App::get('/v1/projects') } $projectId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('projects', $projectId); + $cursorDocument = $dbForPlatform->getDocument('projects', $projectId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Project '{$projectId}' for the 'cursor' value not found."); @@ -349,8 +349,8 @@ App::get('/v1/projects') $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ - 'projects' => $dbForConsole->find('projects', $queries), - 'total' => $dbForConsole->count('projects', $filterQueries, APP_LIMIT_COUNT), + 'projects' => $dbForPlatform->find('projects', $queries), + 'total' => $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_PROJECT_LIST); }); @@ -366,10 +366,10 @@ App::get('/v1/projects/:projectId') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -400,16 +400,16 @@ App::patch('/v1/projects/:projectId') ->param('legalAddress', '', new Text(256), 'Project legal address. Max length: 256 chars.', true) ->param('legalTaxId', '', new Text(256), 'Project legal tax ID. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('name', $name) ->setAttribute('description', $description) ->setAttribute('logo', $logo) @@ -438,11 +438,11 @@ App::patch('/v1/projects/:projectId/team') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('teamId', '', new UID(), 'Team ID of the team to transfer project to.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $teamId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $teamId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); - $team = $dbForConsole->getDocument('teams', $teamId); + $project = $dbForPlatform->getDocument('projects', $projectId); + $team = $dbForPlatform->getDocument('teams', $teamId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -464,30 +464,30 @@ App::patch('/v1/projects/:projectId/team') ->setAttribute('teamId', $teamId) ->setAttribute('teamInternalId', $team->getInternalId()) ->setAttribute('$permissions', $permissions); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project); - $installations = $dbForConsole->find('installations', [ + $installations = $dbForPlatform->find('installations', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($installations as $installation) { $installation->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('installations', $installation->getId(), $installation); + $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } - $repositories = $dbForConsole->find('repositories', [ + $repositories = $dbForPlatform->find('repositories', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($repositories as $repository) { $repository->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('repositories', $repository->getId(), $repository); + $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository); } - $vcsComments = $dbForConsole->find('vcsComments', [ + $vcsComments = $dbForPlatform->find('vcsComments', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($vcsComments as $vcsComment) { $vcsComment->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('vcsComments', $vcsComment->getId(), $vcsComment); + $dbForPlatform->updateDocument('vcsComments', $vcsComment->getId(), $vcsComment); } $response->dynamic($project, Response::MODEL_PROJECT); @@ -507,10 +507,10 @@ App::patch('/v1/projects/:projectId/service') ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -519,7 +519,7 @@ App::patch('/v1/projects/:projectId/service') $services = $project->getAttribute('services', []); $services[$service] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -537,10 +537,10 @@ App::patch('/v1/projects/:projectId/service/all') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -553,7 +553,7 @@ App::patch('/v1/projects/:projectId/service/all') $services[$service] = $status; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -572,10 +572,10 @@ App::patch('/v1/projects/:projectId/api') ->param('api', '', new WhiteList(array_keys(Config::getParam('apis')), true), 'API name.') ->param('status', null, new Boolean(), 'API status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $api, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $api, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -584,7 +584,7 @@ App::patch('/v1/projects/:projectId/api') $apis = $project->getAttribute('apis', []); $apis[$api] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -602,10 +602,10 @@ App::patch('/v1/projects/:projectId/api/all') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'API status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -618,7 +618,7 @@ App::patch('/v1/projects/:projectId/api/all') $apis[$api] = $status; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -639,10 +639,10 @@ App::patch('/v1/projects/:projectId/oauth2') ->param('secret', null, new text(512), 'Provider secret key. Max length: 512 chars.', true) ->param('enabled', null, new Boolean(), 'Provider status. Set to \'false\' to disable new session creation.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -662,7 +662,7 @@ App::patch('/v1/projects/:projectId/oauth2') $providers[$provider . 'Enabled'] = $enabled; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('oAuthProviders', $providers)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('oAuthProviders', $providers)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -680,10 +680,10 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $alerts, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $alerts, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -692,7 +692,7 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') $auths = $project->getAttribute('auths', []); $auths['sessionAlerts'] = $alerts; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -713,9 +713,9 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') ->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.') ->param('mfa', true, new Boolean(true), 'Set to true to show mfa to members of a team.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $userName, bool $userEmail, bool $mfa, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $userName, bool $userEmail, bool $mfa, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -727,7 +727,7 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') $auths['membershipsUserEmail'] = $userEmail; $auths['membershipsMfa'] = $mfa; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -746,10 +746,10 @@ App::patch('/v1/projects/:projectId/auth/limit') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -758,7 +758,7 @@ App::patch('/v1/projects/:projectId/auth/limit') $auths = $project->getAttribute('auths', []); $auths['limit'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -777,10 +777,10 @@ App::patch('/v1/projects/:projectId/auth/duration') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $duration, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -789,7 +789,7 @@ App::patch('/v1/projects/:projectId/auth/duration') $auths = $project->getAttribute('auths', []); $auths['duration'] = $duration; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -809,10 +809,10 @@ App::patch('/v1/projects/:projectId/auth/:method') ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false) ->param('status', false, new Boolean(true), 'Set the status of this auth method.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); $auth = Config::getParam('auth')[$method] ?? []; $authKey = $auth['key'] ?? ''; $status = ($status === '1' || $status === 'true' || $status === 1 || $status === true); @@ -824,7 +824,7 @@ App::patch('/v1/projects/:projectId/auth/:method') $auths = $project->getAttribute('auths', []); $auths[$authKey] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -842,10 +842,10 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -854,7 +854,7 @@ App::patch('/v1/projects/:projectId/auth/password-history') $auths = $project->getAttribute('auths', []); $auths['passwordHistory'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -873,10 +873,10 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -885,7 +885,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') $auths = $project->getAttribute('auths', []); $auths['passwordDictionary'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -904,10 +904,10 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -916,7 +916,7 @@ App::patch('/v1/projects/:projectId/auth/personal-data') $auths = $project->getAttribute('auths', []); $auths['personalDataCheck'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -935,10 +935,10 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -947,7 +947,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') $auths = $project->getAttribute('auths', []); $auths['maxSessions'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -966,8 +966,8 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('numbers', '', new ArrayList(new MockNumber(), 10), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, array $numbers, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, array $numbers, Response $response, Database $dbForPlatform) { $uniqueNumbers = []; foreach ($numbers as $number) { @@ -977,7 +977,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') $uniqueNumbers[$number['phone']] = $number['otp']; } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -987,7 +987,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') $auths['mockNumbers'] = $numbers; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -1005,10 +1005,10 @@ App::delete('/v1/projects/:projectId') ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('user') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') - ->action(function (string $projectId, Response $response, Document $user, Database $dbForConsole, Delete $queueForDeletes) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->action(function (string $projectId, Response $response, Document $user, Database $dbForPlatform, Delete $queueForDeletes) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1019,7 +1019,7 @@ App::delete('/v1/projects/:projectId') ->setType(DELETE_TYPE_DOCUMENT) ->setDocument($project); - if (!$dbForConsole->deleteDocument('projects', $projectId)) { + if (!$dbForPlatform->deleteDocument('projects', $projectId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB'); } @@ -1047,10 +1047,10 @@ App::post('/v1/projects/:projectId/webhooks') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1077,9 +1077,9 @@ App::post('/v1/projects/:projectId/webhooks') 'enabled' => $enabled, ]); - $webhook = $dbForConsole->createDocument('webhooks', $webhook); + $webhook = $dbForPlatform->createDocument('webhooks', $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1098,16 +1098,16 @@ App::get('/v1/projects/:projectId/webhooks') ->label('sdk.response.model', Response::MODEL_WEBHOOK_LIST) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhooks = $dbForConsole->find('webhooks', [ + $webhooks = $dbForPlatform->find('webhooks', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1131,16 +1131,16 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1172,10 +1172,10 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1183,7 +1183,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1205,8 +1205,8 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $webhook->setAttribute('attempts', 0); } - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1224,16 +1224,16 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1244,8 +1244,8 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64))); - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1262,16 +1262,16 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1280,9 +1280,9 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception(Exception::WEBHOOK_NOT_FOUND); } - $dbForConsole->deleteDocument('webhooks', $webhook->getId()); + $dbForPlatform->deleteDocument('webhooks', $webhook->getId()); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1304,10 +1304,10 @@ App::post('/v1/projects/:projectId/keys') ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1330,9 +1330,9 @@ App::post('/v1/projects/:projectId/keys') 'secret' => API_KEY_STANDARD . '_' . \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument('keys', $key); + $key = $dbForPlatform->createDocument('keys', $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1351,16 +1351,16 @@ App::get('/v1/projects/:projectId/keys') ->label('sdk.response.model', Response::MODEL_KEY_LIST) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $keys = $dbForConsole->find('keys', [ + $keys = $dbForPlatform->find('keys', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1384,16 +1384,16 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1421,16 +1421,16 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1444,9 +1444,9 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->setAttribute('scopes', $scopes) ->setAttribute('expire', $expire); - $dbForConsole->updateDocument('keys', $key->getId(), $key); + $dbForPlatform->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -1463,16 +1463,16 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1481,9 +1481,9 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception(Exception::KEY_NOT_FOUND); } - $dbForConsole->deleteDocument('keys', $key->getId()); + $dbForPlatform->deleteDocument('keys', $key->getId()); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1504,10 +1504,10 @@ App::post('/v1/projects/:projectId/jwts') ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, array $scopes, int $duration, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, array $scopes, int $duration, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1543,9 +1543,9 @@ App::post('/v1/projects/:projectId/platforms') ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) ->param('hostname', '', new Hostname(), 'Platform client hostname. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1567,9 +1567,9 @@ App::post('/v1/projects/:projectId/platforms') 'hostname' => $hostname ]); - $platform = $dbForConsole->createDocument('platforms', $platform); + $platform = $dbForPlatform->createDocument('platforms', $platform); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1588,16 +1588,16 @@ App::get('/v1/projects/:projectId/platforms') ->label('sdk.response.model', Response::MODEL_PLATFORM_LIST) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platforms = $dbForConsole->find('platforms', [ + $platforms = $dbForPlatform->find('platforms', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1621,16 +1621,16 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1659,15 +1659,15 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) ->param('hostname', '', new Hostname(), 'Platform client URL. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1682,9 +1682,9 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('store', $store) ->setAttribute('hostname', $hostname); - $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); + $dbForPlatform->updateDocument('platforms', $platform->getId(), $platform); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1702,16 +1702,16 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1720,9 +1720,9 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception(Exception::PLATFORM_NOT_FOUND); } - $dbForConsole->deleteDocument('platforms', $platformId); + $dbForPlatform->deleteDocument('platforms', $platformId); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1750,10 +1750,10 @@ App::patch('/v1/projects/:projectId/smtp') ->param('password', '', new Text(0, 0), 'SMTP server password', true) ->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1814,7 +1814,7 @@ App::patch('/v1/projects/:projectId/smtp') ]; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -1839,10 +1839,10 @@ App::post('/v1/projects/:projectId/smtp/tests') ->param('password', '', new Text(0, 0), 'SMTP server password', true) ->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true) ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForMails') - ->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole, Mail $queueForMails) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1892,12 +1892,12 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1933,10 +1933,10 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1986,12 +1986,12 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('message', '', new Text(0), 'Template message') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2002,7 +2002,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') 'message' => $message ]; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'message' => $message, @@ -2030,10 +2030,10 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->param('senderEmail', '', new Email(), 'Email of the sender', true) ->param('replyTo', '', new Email(), 'Reply to email', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2048,7 +2048,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') 'message' => $message ]; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, @@ -2075,12 +2075,12 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2095,7 +2095,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') unset($template['sms.' . $type . '-' . $locale]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, @@ -2118,10 +2118,10 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2136,7 +2136,7 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') unset($templates['email.' . $type . '-' . $locale]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 8ff921ffeb..0d2fed8e66 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -43,9 +43,9 @@ App::post('/v1/proxy/rules') ->inject('project') ->inject('queueForCertificates') ->inject('queueForEvents') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('dbForProject') - ->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForConsole, Database $dbForProject) { + ->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) { $mainDomain = System::getEnv('_APP_DOMAIN', ''); if ($domain === $mainDomain) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.'); @@ -62,9 +62,9 @@ App::post('/v1/proxy/rules') // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $document = $dbForConsole->getDocument('rules', md5($domain)); + $document = $dbForPlatform->getDocument('rules', md5($domain)); } else { - $document = $dbForConsole->findOne('rules', [ + $document = $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain]), ]); } @@ -145,7 +145,7 @@ App::post('/v1/proxy/rules') } $rule->setAttribute('status', $status); - $rule = $dbForConsole->createDocument('rules', $rule); + $rule = $dbForPlatform->createDocument('rules', $rule); $queueForEvents->setParam('ruleId', $rule->getId()); @@ -171,8 +171,8 @@ App::get('/v1/proxy/rules') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -201,7 +201,7 @@ App::get('/v1/proxy/rules') } $ruleId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('rules', $ruleId); + $cursorDocument = $dbForPlatform->getDocument('rules', $ruleId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Rule '{$ruleId}' for the 'cursor' value not found."); @@ -212,16 +212,16 @@ App::get('/v1/proxy/rules') $filterQueries = Query::groupByType($queries)['filters']; - $rules = $dbForConsole->find('rules', $queries); + $rules = $dbForPlatform->find('rules', $queries); foreach ($rules as $rule) { - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', '')); } $response->dynamic(new Document([ 'rules' => $rules, - 'total' => $dbForConsole->count('rules', $filterQueries, APP_LIMIT_COUNT), + 'total' => $dbForPlatform->count('rules', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_PROXY_RULE_LIST); }); @@ -239,15 +239,15 @@ App::get('/v1/proxy/rules/:ruleId') ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $ruleId, Response $response, Document $project, Database $dbForConsole) { - $rule = $dbForConsole->getDocument('rules', $ruleId); + ->inject('dbForPlatform') + ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) { + $rule = $dbForPlatform->getDocument('rules', $ruleId); if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', '')); @@ -270,17 +270,17 @@ App::delete('/v1/proxy/rules/:ruleId') ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') ->inject('queueForEvents') - ->action(function (string $ruleId, Response $response, Document $project, Database $dbForConsole, Delete $queueForDeletes, Event $queueForEvents) { - $rule = $dbForConsole->getDocument('rules', $ruleId); + ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes, Event $queueForEvents) { + $rule = $dbForPlatform->getDocument('rules', $ruleId); if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } - $dbForConsole->deleteDocument('rules', $rule->getId()); + $dbForPlatform->deleteDocument('rules', $rule->getId()); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) @@ -309,10 +309,10 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('log') - ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForConsole, Log $log) { - $rule = $dbForConsole->getDocument('rules', $ruleId); + ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForPlatform, Log $log) { + $rule = $dbForPlatform->getDocument('rules', $ruleId); if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); @@ -342,7 +342,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') throw new Exception(Exception::RULE_VERIFICATION_FAILED); } - $dbForConsole->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying')); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying')); // Issue a TLS certificate when domain is verified $queueForCertificates @@ -353,7 +353,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') $queueForEvents->setParam('ruleId', $rule->getId()); - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $response->dynamic($rule, Response::MODEL_PROXY_RULE); diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index bbb1d9c3f8..6e81c43ef8 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -42,7 +42,7 @@ use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForConsole, Build $queueForBuilds, callable $getProjectDB, Request $request) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, Request $request) { $errors = []; foreach ($repositories as $resource) { try { @@ -53,7 +53,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $resource->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); $functionId = $resource->getAttribute('resourceId'); @@ -104,7 +104,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForConsole->findOne('vcsComments', [ + $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -125,7 +125,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForConsole->createDocument('vcsComments', new Document([ + $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -146,7 +146,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForConsole->find('vcsComments', [ + $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -319,8 +319,8 @@ App::get('/v1/vcs/github/callback') ->inject('project') ->inject('request') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $providerInstallationId, string $setupAction, string $state, string $code, GitHub $github, Document $user, Document $project, Request $request, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $providerInstallationId, string $setupAction, string $state, string $code, GitHub $github, Document $user, Document $project, Request $request, Response $response, Database $dbForPlatform) { if (empty($state)) { $error = 'Installation requests from organisation members for the Appwrite GitHub App are currently unsupported. To proceed with the installation, login to the Appwrite Console and install the GitHub App.'; throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $error); @@ -339,7 +339,7 @@ App::get('/v1/vcs/github/callback') $redirectSuccess = $state['success'] ?? ''; $redirectFailure = $state['failure'] ?? ''; - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { $error = 'Project with the ID from state could not be found.'; @@ -368,7 +368,7 @@ App::get('/v1/vcs/github/callback') $oauth2ID = $oauth2->getUserID($accessToken); // Makes sure this email is not already used in another identity - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('providerEmail', [$email]), ]); if (!$identity->isEmpty()) { @@ -381,9 +381,9 @@ App::get('/v1/vcs/github/callback') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } else { - $identity = $dbForConsole->createDocument('identities', new Document([ + $identity = $dbForPlatform->createDocument('identities', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::any()), @@ -411,7 +411,7 @@ App::get('/v1/vcs/github/callback') $projectInternalId = $project->getInternalId(); - $installation = $dbForConsole->findOne('installations', [ + $installation = $dbForPlatform->findOne('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), Query::equal('projectInternalId', [$projectInternalId]) ]); @@ -436,12 +436,12 @@ App::get('/v1/vcs/github/callback') 'personal' => $personalSlug === $owner ]); - $installation = $dbForConsole->createDocument('installations', $installation); + $installation = $dbForPlatform->createDocument('installations', $installation); } else { $installation = $installation ->setAttribute('organization', $owner) ->setAttribute('personal', $personalSlug === $owner); - $installation = $dbForConsole->updateDocument('installations', $installation->getId(), $installation); + $installation = $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } } else { $error = 'Installation of the Appwrite GitHub App on organization accounts is restricted to organization owners. As a member of the organization, you do not have the necessary permissions to install this GitHub App. Please contact the organization owner to create the installation from the Appwrite console.'; @@ -480,9 +480,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -541,9 +541,9 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -612,13 +612,13 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $search, GitHub $github, Response $response, Document $project, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $installationId, string $search, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { if (empty($search)) { $search = ""; } - $installation = $dbForConsole->getDocument('installations', $installationId); + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -709,9 +709,9 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->inject('user') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $name, bool $private, GitHub $github, Document $user, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $name, bool $private, GitHub $github, Document $user, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -720,7 +720,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if ($installation->getAttribute('personal', false) === true) { $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); - $identity = $dbForConsole->findOne('identities', [ + $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['github']), Query::equal('userInternalId', [$user->getInternalId()]), ]); @@ -750,7 +750,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); } try { @@ -808,9 +808,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -857,9 +857,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -897,11 +897,11 @@ App::post('/v1/vcs/github/events') ->inject('gitHub') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForBuilds') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -935,36 +935,36 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find functionId from functions table - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push and not when branch is created if (!$providerBranchCreated) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { // TODO: Use worker for this job instead (update function as well) $providerInstallationId = $parsedPayload["installationId"]; - $installations = $dbForConsole->find('installations', [ + $installations = $dbForPlatform->find('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), Query::limit(1000) ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getInternalId()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - Authorization::skip(fn () => $dbForConsole->deleteDocument('repositories', $repository->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - $dbForConsole->deleteDocument('installations', $installation->getId()); + $dbForPlatform->deleteDocument('installations', $installation->getId()); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -993,12 +993,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1007,7 +1007,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1018,7 +1018,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = Authorization::skip(fn () => $dbForConsole->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1045,8 +1045,8 @@ App::get('/v1/vcs/installations') ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1075,7 +1075,7 @@ App::get('/v1/vcs/installations') } $installationId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('installations', $installationId); + $cursorDocument = $dbForPlatform->getDocument('installations', $installationId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Installation '{$installationId}' for the 'cursor' value not found."); @@ -1086,8 +1086,8 @@ App::get('/v1/vcs/installations') $filterQueries = Query::groupByType($queries)['filters']; - $results = $dbForConsole->find('installations', $queries); - $total = $dbForConsole->count('installations', $filterQueries, APP_LIMIT_COUNT); + $results = $dbForPlatform->find('installations', $queries); + $total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT); $response->dynamic(new Document([ 'installations' => $results, @@ -1109,9 +1109,9 @@ App::get('/v1/vcs/installations/:installationId') ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation === false || $installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -1137,16 +1137,16 @@ App::delete('/v1/vcs/installations/:installationId') ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') - ->action(function (string $installationId, Response $response, Document $project, Database $dbForConsole, Delete $queueForDeletes) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->action(function (string $installationId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - if (!$dbForConsole->deleteDocument('installations', $installation->getId())) { + if (!$dbForPlatform->deleteDocument('installations', $installation->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove installation from DB'); } @@ -1174,17 +1174,17 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('request') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForBuilds') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForConsole->getDocument('repositories', $repositoryId, [ + $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ Query::equal('projectInternalId', [$project->getInternalId()]) ])); @@ -1201,7 +1201,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = Authorization::skip(fn () => $dbForConsole->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1225,7 +1225,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerBranch = \explode(':', $pullRequestResponse['head']['label'])[1] ?? ''; $providerCommitHash = $pullRequestResponse['head']['sha'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 54e6e1e791..32cc68fecf 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -46,7 +46,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -57,10 +57,10 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); + $route = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); } else { $route = Authorization::skip( - fn () => $dbForConsole->find('rules', [ + fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) ]) @@ -89,7 +89,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $projectId = $route->getAttribute('projectId'); $project = Authorization::skip( - fn () => $dbForConsole->getDocument('projects', $projectId) + fn () => $dbForPlatform->getDocument('projects', $projectId) ); if (array_key_exists('proxy', $project->getAttribute('services', []))) { $status = $project->getAttribute('services', [])['proxy']; @@ -135,7 +135,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $requestHeaders = $request->getHeaders(); - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); @@ -459,7 +459,7 @@ App::init() ->inject('response') ->inject('console') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('locale') ->inject('localeCodes') @@ -471,7 +471,7 @@ App::init() ->inject('queueForFunctions') ->inject('isResourceBlocked') ->inject('previewHostname') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) { /* * Appwrite Router */ @@ -479,7 +479,7 @@ App::init() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { return; } } @@ -529,9 +529,9 @@ App::init() } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); + $domainDocument = $dbForPlatform->getDocument('rules', md5($envDomain)); } else { - $domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]); + $domainDocument = $dbForPlatform->findOne('rules', [Query::orderAsc('$id')]); } $mainDomain = !$domainDocument->isEmpty() ? $domainDocument->getAttribute('domain') : $domain->get(); } @@ -541,9 +541,9 @@ App::init() } else { // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); + $domainDocument = $dbForPlatform->getDocument('rules', md5($domain->get())); } else { - $domainDocument = $dbForConsole->findOne('rules', [ + $domainDocument = $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain->get()]) ]); } @@ -559,7 +559,7 @@ App::init() 'projectInternalId' => 'console' ]); - $domainDocument = $dbForConsole->createDocument('rules', $domainDocument); + $domainDocument = $dbForPlatform->createDocument('rules', $domainDocument); Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); @@ -695,7 +695,7 @@ App::options() ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') ->inject('queueForUsage') @@ -703,7 +703,7 @@ App::options() ->inject('geodb') ->inject('isResourceBlocked') ->inject('previewHostname') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { /* * Appwrite Router */ @@ -711,7 +711,7 @@ App::options() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) { return; } } @@ -994,7 +994,7 @@ App::get('/robots.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') ->inject('queueForUsage') @@ -1002,7 +1002,7 @@ App::get('/robots.txt') ->inject('geodb') ->inject('isResourceBlocked') ->inject('previewHostname') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1010,7 +1010,7 @@ App::get('/robots.txt') $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); + router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); } }); @@ -1022,7 +1022,7 @@ App::get('/humans.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') ->inject('queueForUsage') @@ -1030,7 +1030,7 @@ App::get('/humans.txt') ->inject('geodb') ->inject('isResourceBlocked') ->inject('previewHostname') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1038,7 +1038,7 @@ App::get('/humans.txt') $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); + router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname); } }); @@ -1102,9 +1102,9 @@ App::get('/v1/ping') ->label('event', 'projects.[projectId].ping') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (Response $response, Document $project, Database $dbForConsole, Event $queueForEvents) { + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { if ($project->isEmpty()) { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1116,8 +1116,8 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForConsole, $project) { - $dbForConsole->updateDocument('projects', $project->getId(), $project); + Authorization::skip(function () use ($dbForPlatform, $project) { + $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); $queueForEvents diff --git a/app/controllers/mock.php b/app/controllers/mock.php index bc071fc885..afbb176b7e 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -162,15 +162,15 @@ App::post('/v1/mock/api-key-unprefixed') ->label('docs', false) ->param('projectId', '', new UID(), 'Project ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { $isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development'; if (!$isDevelopment) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -195,9 +195,9 @@ App::post('/v1/mock/api-key-unprefixed') 'secret' => \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument('keys', $key); + $key = $dbForPlatform->createDocument('keys', $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -214,15 +214,15 @@ App::get('/v1/mock/github/callback') ->inject('gitHub') ->inject('project') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $providerInstallationId, string $projectId, GitHub $github, Document $project, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $providerInstallationId, string $projectId, GitHub $github, Document $project, Response $response, Database $dbForPlatform) { $isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development'; if (!$isDevelopment) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { $error = 'Project with the ID from state could not be found.'; @@ -256,7 +256,7 @@ App::get('/v1/mock/github/callback') 'personal' => false ]); - $installation = $dbForConsole->createDocument('installations', $installation); + $installation = $dbForPlatform->createDocument('installations', $installation); } $response->json([ diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 91883b0895..a0f65eb484 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -184,7 +184,7 @@ App::init() ->groups(['api']) ->inject('utopia') ->inject('request') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('dbForProject') ->inject('project') ->inject('user') @@ -192,7 +192,7 @@ App::init() ->inject('servers') ->inject('mode') ->inject('team') - ->action(function (App $utopia, Request $request, Database $dbForConsole, Database $dbForProject, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) { + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) { $route = $utopia->getRoute(); if ($project->isEmpty()) { @@ -284,8 +284,8 @@ App::init() $accessedAt = $key->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DateTime::now()); - $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('keys', $key->getId(), $key); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } $sdkValidator = new WhiteList($servers, true); @@ -298,8 +298,8 @@ App::init() /** Update access time as well */ $key->setAttribute('accessedAt', Datetime::now()); - $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('keys', $key->getId(), $key); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } } @@ -343,7 +343,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -358,7 +358,7 @@ App::init() if (APP_MODE_ADMIN !== $mode) { $dbForProject->updateDocument('users', $user->getId(), $user); } else { - $dbForConsole->updateDocument('users', $user->getId(), $user); + $dbForPlatform->updateDocument('users', $user->getId(), $user); } } } diff --git a/app/http.php b/app/http.php index c4e48a7f69..74b829c384 100644 --- a/app/http.php +++ b/app/http.php @@ -174,8 +174,8 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg do { try { $attempts++; - $dbForConsole = $app->getResource('dbForConsole'); - /** @var Utopia\Database\Database $dbForConsole */ + $dbForPlatform = $app->getResource('dbForPlatform'); + /** @var Utopia\Database\Database $dbForPlatform */ break; // leave the do-while if successful } catch (\Throwable $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); @@ -190,18 +190,18 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg try { Console::success('[Setup] - Creating console database...'); - $dbForConsole->create(); + $dbForPlatform->create(); } catch (Duplicate) { Console::success('[Setup] - Skip: metadata table already exists'); } - if ($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) { - $audit = new Audit($dbForConsole); + if ($dbForPlatform->getCollection(Audit::COLLECTION)->isEmpty()) { + $audit = new Audit($dbForPlatform); $audit->setup(); } - if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit("", 0, 1, $dbForConsole); + if ($dbForPlatform->getCollection(TimeLimit::COLLECTION)->isEmpty()) { + $adapter = new TimeLimit("", 0, 1, $dbForPlatform); $adapter->setup(); } @@ -212,7 +212,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg if (($collection['$collection'] ?? '') !== Database::METADATA) { continue; } - if (!$dbForConsole->getCollection($key)->isEmpty()) { + if (!$dbForPlatform->getCollection($key)->isEmpty()) { continue; } @@ -221,12 +221,12 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); - $dbForConsole->createCollection($key, $attributes, $indexes); + $dbForPlatform->createCollection($key, $attributes, $indexes); } - if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) { + if ($dbForPlatform->getDocument('buckets', 'default')->isEmpty() && !$dbForPlatform->exists($dbForPlatform->getDatabase(), 'bucket_1')) { Console::success('[Setup] - Creating default bucket...'); - $dbForConsole->createDocument('buckets', new Document([ + $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('default'), '$collection' => ID::custom('buckets'), 'name' => 'Default', @@ -246,7 +246,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Default', ])); - $bucket = $dbForConsole->getDocument('buckets', 'default'); + $bucket = $dbForPlatform->getDocument('buckets', 'default'); Console::success('[Setup] - Creating files collection for default bucket...'); $files = $collections['buckets']['files'] ?? []; @@ -257,7 +257,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $attributes = \array_map(fn ($attribute) => new Document($attribute), $files['attributes']); $indexes = \array_map(fn (array $index) => new Document($index), $files['indexes']); - $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); + $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } $projectCollections = $collections['projects']; @@ -441,10 +441,10 @@ $http->on('Task', function () use ($register, $domains) { App::setResource('pools', fn () => $pools); $app = new App('UTC'); - /** @var Utopia\Database\Database $dbForConsole */ - $dbForConsole = $app->getResource('dbForConsole'); + /** @var Utopia\Database\Database $dbForPlatform */ + $dbForPlatform = $app->getResource('dbForPlatform'); - Console::loop(function () use ($dbForConsole, $domains, &$lastSyncUpdate) { + Console::loop(function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { try { $time = DateTime::now(); $limit = 1000; @@ -462,7 +462,7 @@ $http->on('Task', function () use ($register, $domains) { $queries[] = Query::equal('resourceType', ['function']); $results = []; try { - $results = Authorization::skip(fn () => $dbForConsole->find('rules', $queries)); + $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); } catch (Throwable $th) { Console::error($th->getMessage()); } diff --git a/app/init.php b/app/init.php index 30ece74553..109849fdce 100644 --- a/app/init.php +++ b/app/init.php @@ -1213,12 +1213,12 @@ App::setResource('clients', function ($request, $console, $project) { return \array_unique($clients); }, ['request', 'console', 'project']); -App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) { +App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) { /** @var Appwrite\Utopia\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Document $project */ /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Database $dbForConsole */ + /** @var Utopia\Database\Database $dbForPlatform */ /** @var string $mode */ Authorization::setDefaultStatus(true); @@ -1267,13 +1267,13 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $user = new Document([]); } else { if ($project->getId() === 'console') { - $user = $dbForConsole->getDocument('users', Auth::$unique); + $user = $dbForPlatform->getDocument('users', Auth::$unique); } else { $user = $dbForProject->getDocument('users', Auth::$unique); } } } else { - $user = $dbForConsole->getDocument('users', Auth::$unique); + $user = $dbForPlatform->getDocument('users', Auth::$unique); } if ( @@ -1316,14 +1316,14 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons } $dbForProject->setMetadata('user', $user->getId()); - $dbForConsole->setMetadata('user', $user->getId()); + $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForConsole']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']); -App::setResource('project', function ($dbForConsole, $request, $console) { +App::setResource('project', function ($dbForPlatform, $request, $console) { /** @var Appwrite\Utopia\Request $request */ - /** @var Utopia\Database\Database $dbForConsole */ + /** @var Utopia\Database\Database $dbForPlatform */ /** @var Utopia\Database\Document $console */ $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); @@ -1332,10 +1332,10 @@ App::setResource('project', function ($dbForConsole, $request, $console) { return $console; } - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; -}, ['dbForConsole', 'request', 'console']); +}, ['dbForPlatform', 'request', 'console']); App::setResource('session', function (Document $user) { if ($user->isEmpty()) { @@ -1400,9 +1400,9 @@ App::setResource('console', function () { ]); }, []); -App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, Cache $cache, Document $project) { +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -1440,9 +1440,9 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, } return $database; -}, ['pools', 'dbForConsole', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project']); -App::setResource('dbForConsole', function (Group $pools, Cache $cache) { +App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $dbAdapter = $pools ->get('console') ->pop() @@ -1460,12 +1460,12 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) { return $database; }, ['pools', 'cache']); -App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -1514,7 +1514,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $database; }; -}, ['pools', 'dbForConsole', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); App::setResource('cache', function (Group $pools) { $list = Config::getParam('pools-cache', []); @@ -1796,7 +1796,7 @@ App::setResource('plan', function (array $plan = []) { return []; }); -App::setResource('team', function (Document $project, Database $dbForConsole, App $utopia, Request $request) { +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { $teamInternalId = ''; if ($project->getId() !== 'console') { $teamInternalId = $project->getAttribute('teamInternalId', ''); @@ -1806,23 +1806,23 @@ App::setResource('team', function (Document $project, Database $dbForConsole, Ap if (str_starts_with($path, '/v1/projects/:projectId')) { $uri = $request->getURI(); $pid = explode('/', $uri)[3]; - $p = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $pid)); + $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); - $team = Authorization::skip(fn () => $dbForConsole->getDocument('teams', $teamId)); + $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } - $team = Authorization::skip(function () use ($dbForConsole, $teamInternalId) { - return $dbForConsole->findOne('teams', [ + $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + return $dbForPlatform->findOne('teams', [ Query::equal('$internalId', [$teamInternalId]), ]); }); return $team; -}, ['project', 'dbForConsole', 'utopia', 'request']); +}, ['project', 'dbForPlatform', 'utopia', 'request']); App::setResource( 'isResourceBlocked', diff --git a/app/worker.php b/app/worker.php index 7e4eafeea2..2c7d8acb22 100644 --- a/app/worker.php +++ b/app/worker.php @@ -41,7 +41,7 @@ Runtime::enableCoroutine(SWOOLE_HOOK_ALL); Server::setResource('register', fn () => $register); -Server::setResource('dbForConsole', function (Cache $cache, Registry $register) { +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $database = $pools ->get('console') @@ -54,7 +54,7 @@ Server::setResource('dbForConsole', function (Cache $cache, Registry $register) return $adapter; }, ['cache', 'register']); -Server::setResource('project', function (Message $message, Database $dbForConsole) { +Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; $project = new Document($payload['project'] ?? []); @@ -62,12 +62,12 @@ Server::setResource('project', function (Message $message, Database $dbForConsol return $project; } - return $dbForConsole->getDocument('projects', $project->getId()); -}, ['message', 'dbForConsole']); + return $dbForPlatform->getDocument('projects', $project->getId()); +}, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForConsole) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } $pools = $register->get('pools'); @@ -108,14 +108,14 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, } return $database; -}, ['cache', 'register', 'message', 'project', 'dbForConsole']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -170,7 +170,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso return $database; }; -}, ['pools', 'dbForConsole', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400)); diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index 40e72dc683..55f4f25843 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -23,13 +23,13 @@ class Maintenance extends Action { $this ->desc('Schedules maintenance tasks and publishes them to our queues') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForCertificates') ->inject('queueForDeletes') - ->callback(fn (Database $dbForConsole, Certificate $queueForCertificates, Delete $queueForDeletes) => $this->action($dbForConsole, $queueForCertificates, $queueForDeletes)); + ->callback(fn (Database $dbForPlatform, Certificate $queueForCertificates, Delete $queueForDeletes) => $this->action($dbForPlatform, $queueForCertificates, $queueForDeletes)); } - public function action(Database $dbForConsole, Certificate $queueForCertificates, Delete $queueForDeletes): void + public function action(Database $dbForPlatform, Certificate $queueForCertificates, Delete $queueForDeletes): void { Console::title('Maintenance V1'); Console::success(APP_NAME . ' maintenance process v1 has started'); @@ -41,19 +41,19 @@ class Maintenance extends Action $cacheRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days $schedulesDeletionRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day - Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForConsole, $queueForDeletes, $queueForCertificates) { + Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $queueForDeletes, $queueForCertificates) { $time = DateTime::now(); Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); - $this->foreachProject($dbForConsole, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { + $this->foreachProject($dbForPlatform, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { $queueForDeletes->setProject($project); $this->notifyProjects($queueForDeletes, $usageStatsRetentionHourly); }); $this->notifyDeleteConnections($queueForDeletes); - $this->renewCertificates($dbForConsole, $queueForCertificates); + $this->renewCertificates($dbForPlatform, $queueForCertificates); $this->notifyDeleteCache($cacheRetention, $queueForDeletes); $this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes); }, $interval, $delay); @@ -72,7 +72,7 @@ class Maintenance extends Action $this->notifyDeleteExpiredSessions($queueForDeletes); } - protected function foreachProject(Database $dbForConsole, callable $callback): void + protected function foreachProject(Database $dbForPlatform, callable $callback): void { // TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document $count = 0; @@ -82,7 +82,7 @@ class Maintenance extends Action $executionStart = \microtime(true); while ($sum === $limit) { - $projects = $dbForConsole->find('projects', [Query::limit($limit), Query::offset($chunk * $limit)]); + $projects = $dbForPlatform->find('projects', [Query::limit($limit), Query::offset($chunk * $limit)]); $chunk++; @@ -143,11 +143,11 @@ class Maintenance extends Action ->trigger(); } - private function renewCertificates(Database $dbForConsole, Certificate $queueForCertificate): void + private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void { $time = DateTime::now(); - $certificates = $dbForConsole->find('certificates', [ + $certificates = $dbForPlatform->find('certificates', [ Query::lessThan('attempts', 5), // Maximum 5 attempts Query::isNotNull('renewDate'), Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index dcba59bb1d..4efa78ed4b 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -30,12 +30,12 @@ class Migrate extends Action ->desc('Migrate Appwrite to new version') /** @TODO APP_VERSION_STABLE needs to be defined */ ->param('version', APP_VERSION_STABLE, new Text(8), 'Version to migrate to.', true) - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') - ->callback(function ($version, $dbForConsole, $getProjectDB, Registry $register) { - \Co\run(function () use ($version, $dbForConsole, $getProjectDB, $register) { - $this->action($version, $dbForConsole, $getProjectDB, $register); + ->callback(function ($version, $dbForPlatform, $getProjectDB, Registry $register) { + \Co\run(function () use ($version, $dbForPlatform, $getProjectDB, $register) { + $this->action($version, $dbForPlatform, $getProjectDB, $register); }); }); } @@ -58,7 +58,7 @@ class Migrate extends Action } } - public function action(string $version, Database $dbForConsole, callable $getProjectDB, Registry $register) + public function action(string $version, Database $dbForPlatform, callable $getProjectDB, Registry $register) { Authorization::disable(); if (!array_key_exists($version, Migration::$versions)) { @@ -93,10 +93,10 @@ class Migrate extends Action $count = 0; try { - $totalProjects = $dbForConsole->count('projects') + 1; + $totalProjects = $dbForPlatform->count('projects') + 1; } catch (\Throwable $th) { - $dbForConsole->setNamespace('_console'); - $totalProjects = $dbForConsole->count('projects') + 1; + $dbForPlatform->setNamespace('_console'); + $totalProjects = $dbForPlatform->count('projects') + 1; } $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; @@ -120,7 +120,7 @@ class Migrate extends Action $projectDB = $getProjectDB($project); $projectDB->disableValidation(); $migration - ->setProject($project, $projectDB, $dbForConsole) + ->setProject($project, $projectDB, $dbForPlatform) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -132,7 +132,7 @@ class Migrate extends Action } $sum = \count($projects); - $projects = $dbForConsole->find('projects', [Query::limit($limit), Query::offset($offset)]); + $projects = $dbForPlatform->find('projects', [Query::limit($limit), Query::offset($offset)]); $offset = $offset + $limit; $count = $count + $sum; diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index a1b85c341f..10623e7fa5 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -25,7 +25,7 @@ abstract class ScheduleBase extends Action abstract public static function getName(): string; abstract public static function getSupportedResource(): string; abstract public static function getCollectionId(): string; - abstract protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void; + abstract protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void; public function __construct() { @@ -34,9 +34,9 @@ abstract class ScheduleBase extends Action $this ->desc("Execute {$type}s scheduled in Appwrite") ->inject('pools') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') - ->callback(fn (Group $pools, Database $dbForConsole, callable $getProjectDB) => $this->action($pools, $dbForConsole, $getProjectDB)); + ->callback(fn (Group $pools, Database $dbForPlatform, callable $getProjectDB) => $this->action($pools, $dbForPlatform, $getProjectDB)); } /** @@ -44,7 +44,7 @@ abstract class ScheduleBase extends Action * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute * 3. Create timer that prepares coroutines for soon-to-execute schedules. When it's ready, coroutine sleeps until exact time before sending request to worker. */ - public function action(Group $pools, Database $dbForConsole, callable $getProjectDB): void + public function action(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { Console::title(\ucfirst(static::getSupportedResource()) . ' scheduler V1'); Console::success(APP_NAME . ' ' . \ucfirst(static::getSupportedResource()) . ' scheduler v1 has started'); @@ -56,8 +56,8 @@ abstract class ScheduleBase extends Action * @throws Exception * @var Document $schedule */ - $getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array { - $project = $dbForConsole->getDocument('projects', $schedule->getAttribute('projectId')); + $getSchedule = function (Document $schedule) use ($dbForPlatform, $getProjectDB): array { + $project = $dbForPlatform->getDocument('projects', $schedule->getAttribute('projectId')); $resource = $getProjectDB($project)->getDocument( static::getCollectionId(), @@ -91,7 +91,7 @@ abstract class ScheduleBase extends Action $paginationQueries[] = Query::cursorAfter($latestDocument); } - $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ + $results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [ Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), Query::equal('resourceType', [static::getSupportedResource()]), Query::equal('active', [true]), @@ -119,11 +119,11 @@ abstract class ScheduleBase extends Action Console::success("Starting timers at " . DateTime::now()); - run(function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools, $getProjectDB) { + run(function () use ($dbForPlatform, &$lastSyncUpdate, $getSchedule, $pools, $getProjectDB) { /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, &$lastSyncUpdate, $getSchedule, $pools) { $time = DateTime::now(); $timerStart = \microtime(true); @@ -141,7 +141,7 @@ abstract class ScheduleBase extends Action $paginationQueries[] = Query::cursorAfter($latestDocument); } - $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ + $results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [ Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), Query::equal('resourceType', [static::getSupportedResource()]), Query::greaterThanEqual('resourceUpdatedAt', $lastSyncUpdate), @@ -179,10 +179,10 @@ abstract class ScheduleBase extends Action Timer::tick( static::ENQUEUE_TIMER * 1000, - fn () => $this->enqueueResources($pools, $dbForConsole, $getProjectDB) + fn () => $this->enqueueResources($pools, $dbForPlatform, $getProjectDB) ); - $this->enqueueResources($pools, $dbForConsole, $getProjectDB); + $this->enqueueResources($pools, $dbForPlatform, $getProjectDB); }); } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 73a2814397..50beb48e9d 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -27,7 +27,7 @@ class ScheduleExecutions extends ScheduleBase return 'executions'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { $queue = $pools->get('queue')->pop(); $connection = $queue->getResource(); @@ -36,7 +36,7 @@ class ScheduleExecutions extends ScheduleBase foreach ($this->schedules as $schedule) { if (!$schedule['active']) { - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); @@ -50,7 +50,7 @@ class ScheduleExecutions extends ScheduleBase continue; } - $data = $dbForConsole->getDocument( + $data = $dbForPlatform->getDocument( 'schedules', $schedule['$id'], )->getAttribute('data', []); @@ -74,7 +74,7 @@ class ScheduleExecutions extends ScheduleBase ->trigger(); }); - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 4d57902330..156ff1e31d 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -31,7 +31,7 @@ class ScheduleFunctions extends ScheduleBase return 'functions'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { $timerStart = \microtime(true); $time = DateTime::now(); diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index b9d8e2a282..2136e62f08 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -26,7 +26,7 @@ class ScheduleMessages extends ScheduleBase return 'messages'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { foreach ($this->schedules as $schedule) { if (!$schedule['active']) { @@ -40,7 +40,7 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $pools, $dbForConsole) { + \go(function () use ($schedule, $pools, $dbForPlatform) { $queue = $pools->get('queue')->pop(); $connection = $queue->getResource(); $queueForMessaging = new Messaging($connection); @@ -51,7 +51,7 @@ class ScheduleMessages extends ScheduleBase ->setProject($schedule['project']) ->trigger(); - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index f71de98d95..0f1332d821 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -61,7 +61,7 @@ class Specs extends Action // Mock dependencies App::setResource('request', fn () => $this->getRequest()); App::setResource('response', fn () => $response); - App::setResource('dbForConsole', fn () => new Database(new MySQL(''), new Cache(new None()))); + App::setResource('dbForPlatform', fn () => new Database(new MySQL(''), new Cache(new None()))); App::setResource('dbForProject', fn () => new Database(new MySQL(''), new Cache(new None()))); $platforms = [ diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 19ff83acd2..bef78a7514 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -46,7 +46,7 @@ class Builds extends Action $this ->desc('Builds worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') ->inject('queueForFunctions') ->inject('queueForUsage') @@ -54,12 +54,12 @@ class Builds extends Action ->inject('dbForProject') ->inject('deviceForFunctions') ->inject('log') - ->callback(fn ($message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log) => $this->action($message, $dbForConsole, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log)); + ->callback(fn ($message, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log) => $this->action($message, $dbForPlatform, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log)); } /** * @param Message $message - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Event $queueForEvents * @param Func $queueForFunctions * @param Usage $queueForUsage @@ -70,7 +70,7 @@ class Builds extends Action * @return void * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $queueForUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log): void + public function action(Message $message, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $queueForUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log): void { $payload = $message->getPayload() ?? []; @@ -92,7 +92,7 @@ class Builds extends Action case BUILD_TYPE_RETRY: Console::info('Creating build for deployment: ' . $deployment->getId()); $github = new GitHub($cache); - $this->buildDeployment($deviceForFunctions, $queueForFunctions, $queueForEvents, $queueForUsage, $dbForConsole, $dbForProject, $github, $project, $resource, $deployment, $template, $log); + $this->buildDeployment($deviceForFunctions, $queueForFunctions, $queueForEvents, $queueForUsage, $dbForPlatform, $dbForProject, $github, $project, $resource, $deployment, $template, $log); break; default: @@ -105,7 +105,7 @@ class Builds extends Action * @param Func $queueForFunctions * @param Event $queueForEvents * @param Usage $queueForUsage - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @param GitHub $github * @param Document $project @@ -117,7 +117,7 @@ class Builds extends Action * @throws \Utopia\Database\Exception * @throws Exception */ - protected function buildDeployment(Device $deviceForFunctions, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Database $dbForConsole, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, Log $log): void + protected function buildDeployment(Device $deviceForFunctions, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Database $dbForPlatform, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, Log $log): void { $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); @@ -199,7 +199,7 @@ class Builds extends Action $repositoryName = ''; if ($isVcsEnabled) { - $installation = $dbForConsole->getDocument('installations', $installationId); + $installation = $dbForPlatform->getDocument('installations', $installationId); $providerInstallationId = $installation->getAttribute('providerInstallationId'); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -418,7 +418,7 @@ class Builds extends Action $directorySize = $deviceForFunctions->getFileSize($source); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize)); - $this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); + $this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForPlatform); } /** Request the executor to build the code... */ @@ -426,7 +426,7 @@ class Builds extends Action $build = $dbForProject->updateDocument('builds', $buildId, $build); if ($isVcsEnabled) { - $this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); + $this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForPlatform); } /** Trigger Webhook */ @@ -640,7 +640,7 @@ class Builds extends Action $build = $dbForProject->updateDocument('builds', $buildId, $build); if ($isVcsEnabled) { - $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); + $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForPlatform); } Console::success("Build id: $buildId created"); @@ -661,12 +661,12 @@ class Builds extends Action /** Update function schedule */ // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } catch (\Throwable $th) { if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); @@ -683,7 +683,7 @@ class Builds extends Action $build = $dbForProject->updateDocument('builds', $buildId, $build); if ($isVcsEnabled) { - $this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); + $this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForPlatform); } } finally { /** @@ -742,7 +742,7 @@ class Builds extends Action * @param Document $function * @param string $deploymentId * @param Database $dbForProject - * @param Database $dbForConsole + * @param Database $dbForPlatform * @return void * @throws Structure * @throws \Utopia\Database\Exception @@ -750,7 +750,7 @@ class Builds extends Action * @throws Conflict * @throws Restricted */ - protected function runGitAction(string $status, GitHub $github, string $providerCommitHash, string $owner, string $repositoryName, Document $project, Document $function, string $deploymentId, Database $dbForProject, Database $dbForConsole): void + protected function runGitAction(string $status, GitHub $github, string $providerCommitHash, string $owner, string $repositoryName, Document $project, Document $function, string $deploymentId, Database $dbForProject, Database $dbForPlatform): void { if ($function->getAttribute('providerSilentMode', false) === true) { return; @@ -795,7 +795,7 @@ class Builds extends Action $retries++; try { - $dbForConsole->createDocument('vcsCommentLocks', new Document([ + $dbForPlatform->createDocument('vcsCommentLocks', new Document([ '$id' => $commentId ])); break; @@ -815,7 +815,7 @@ class Builds extends Action $comment->addBuild($project, $function, $status, $deployment->getId(), ['type' => 'logs']); $github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment()); } finally { - $dbForConsole->deleteDocument('vcsCommentLocks', $commentId); + $dbForPlatform->deleteDocument('vcsCommentLocks', $commentId); } } } diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 4f32877fcf..0ae40b2df0 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -43,21 +43,21 @@ class Certificates extends Action $this ->desc('Certificates worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForMails') ->inject('queueForEvents') ->inject('queueForFunctions') ->inject('log') ->inject('certificates') ->callback( - fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates) => - $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates) + fn (Message $message, Database $dbForPlatform, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates) => + $this->action($message, $dbForPlatform, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates) ); } /** * @param Message $message - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents * @param Func $queueForFunctions @@ -67,7 +67,7 @@ class Certificates extends Action * @throws Throwable * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates): void + public function action(Message $message, Database $dbForPlatform, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates): void { $payload = $message->getPayload() ?? []; @@ -81,12 +81,12 @@ class Certificates extends Action $log->addTag('domain', $domain->get()); - $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates, $skipRenewCheck); + $this->execute($domain, $dbForPlatform, $queueForMails, $queueForEvents, $queueForFunctions, $log, $certificates, $skipRenewCheck); } /** * @param Domain $domain - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents * @param Func $queueForFunctions @@ -96,7 +96,7 @@ class Certificates extends Action * @throws Throwable * @throws \Utopia\Database\Exception */ - private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates, bool $skipRenewCheck = false): void + private function execute(Domain $domain, Database $dbForPlatform, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, CertificatesAdapter $certificates, bool $skipRenewCheck = false): void { /** * 1. Read arguments and validate domain @@ -128,7 +128,7 @@ class Certificates extends Action */ // Get current certificate - $certificate = $dbForConsole->findOne('certificates', [Query::equal('domain', [$domain->get()])]); + $certificate = $dbForPlatform->findOne('certificates', [Query::equal('domain', [$domain->get()])]); // If we don't have certificate for domain yet, let's create new document. At the end we save it if ($certificate->isEmpty()) { @@ -185,7 +185,7 @@ class Certificates extends Action $certificate->setAttribute('updated', DateTime::now()); // Save all changes we made to certificate document into database - $this->saveCertificateDocument($domain->get(), $certificate, $success, $dbForConsole, $queueForEvents, $queueForFunctions); + $this->saveCertificateDocument($domain->get(), $certificate, $success, $dbForPlatform, $queueForEvents, $queueForFunctions); } } @@ -195,7 +195,7 @@ class Certificates extends Action * @param string $domain Domain name that certificate is for * @param Document $certificate Certificate document that we need to save * @param bool $success - * @param Database $dbForConsole Database connection for console + * @param Database $dbForPlatform Database connection for console * @param Event $queueForEvents * @param Func $queueForFunctions * @return void @@ -204,21 +204,21 @@ class Certificates extends Action * @throws Conflict * @throws Structure */ - private function saveCertificateDocument(string $domain, Document $certificate, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void + private function saveCertificateDocument(string $domain, Document $certificate, bool $success, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions): void { // Check if update or insert required - $certificateDocument = $dbForConsole->findOne('certificates', [Query::equal('domain', [$domain])]); + $certificateDocument = $dbForPlatform->findOne('certificates', [Query::equal('domain', [$domain])]); if (!$certificateDocument->isEmpty()) { // Merge new data with current data $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); - $certificate = $dbForConsole->updateDocument('certificates', $certificate->getId(), $certificate); + $certificate = $dbForPlatform->updateDocument('certificates', $certificate->getId(), $certificate); } else { $certificate->removeAttribute('$internalId'); - $certificate = $dbForConsole->createDocument('certificates', $certificate); + $certificate = $dbForPlatform->createDocument('certificates', $certificate); } $certificateId = $certificate->getId(); - $this->updateDomainDocuments($certificateId, $domain, $success, $dbForConsole, $queueForEvents, $queueForFunctions); + $this->updateDomainDocuments($certificateId, $domain, $success, $dbForPlatform, $queueForEvents, $queueForFunctions); } /** @@ -337,13 +337,13 @@ class Certificates extends Action * * @return void */ - private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void + private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions): void { // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $dbForConsole->getDocument('rules', md5($domain)); + $rule = $dbForPlatform->getDocument('rules', md5($domain)); } else { - $rule = $dbForConsole->findOne('rules', [ + $rule = $dbForPlatform->findOne('rules', [ Query::equal('domain', [$domain]), ]); } @@ -351,7 +351,7 @@ class Certificates extends Action if (!$rule->isEmpty()) { $rule->setAttribute('certificateId', $certificateId); $rule->setAttribute('status', $success ? 'verified' : 'unverified'); - $dbForConsole->updateDocument('rules', $rule->getId(), $rule); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); $projectId = $rule->getAttribute('projectId'); @@ -360,7 +360,7 @@ class Certificates extends Action return; } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { return; diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index f9073465cd..9c11dd4090 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -34,21 +34,21 @@ class Databases extends Action $this ->desc('Databases worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('dbForProject') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Database $dbForProject, Log $log) => $this->action($message, $dbForConsole, $dbForProject, $log)); + ->callback(fn (Message $message, Database $dbForPlatform, Database $dbForProject, Log $log) => $this->action($message, $dbForPlatform, $dbForProject, $log)); } /** * @param Message $message - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @param Log $log * @return void * @throws \Exception */ - public function action(Message $message, Database $dbForConsole, Database $dbForProject, Log $log): void + public function action(Message $message, Database $dbForPlatform, Database $dbForProject, Log $log): void { $payload = $message->getPayload() ?? []; @@ -74,10 +74,10 @@ class Databases extends Action match (\strval($type)) { DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $project, $dbForProject), DATABASE_TYPE_DELETE_COLLECTION => $this->deleteCollection($database, $collection, $project, $dbForProject), - DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForConsole, $dbForProject), + DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject), + DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject), + DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject), + DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject), default => throw new \Exception('No database operation for type: ' . \strval($type)), }; } @@ -87,7 +87,7 @@ class Databases extends Action * @param Document $collection * @param Document $attribute * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @return void * @throws Authorization @@ -95,7 +95,7 @@ class Databases extends Action * @throws \Exception * @throws \Throwable */ - private function createAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void + private function createAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -134,7 +134,7 @@ class Databases extends Action $formatOptions = $attribute->getAttribute('formatOptions', []); $filters = $attribute->getAttribute('filters', []); $options = $attribute->getAttribute('options', []); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); try { switch ($type) { @@ -211,7 +211,7 @@ class Databases extends Action * @param Document $collection * @param Document $attribute * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @return void * @throws Authorization @@ -219,7 +219,7 @@ class Databases extends Action * @throws \Exception * @throws \Throwable **/ - private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void + private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -239,7 +239,7 @@ class Databases extends Action $key = $attribute->getAttribute('key', ''); $status = $attribute->getAttribute('status', ''); $type = $attribute->getAttribute('type', ''); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); $options = $attribute->getAttribute('options', []); $relatedAttribute = new Document(); $relatedCollection = new Document(); @@ -356,7 +356,7 @@ class Databases extends Action } if ($exists) { // Delete the duplicate if created, else update in db - $this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject); + $this->deleteIndex($database, $collection, $index, $project, $dbForPlatform, $dbForProject); } else { $dbForProject->updateDocument('indexes', $index->getId(), $index); } @@ -377,7 +377,7 @@ class Databases extends Action * @param Document $collection * @param Document $index * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @return void * @throws Authorization @@ -386,7 +386,7 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void + private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -408,7 +408,7 @@ class Databases extends Action $attributes = $index->getAttribute('attributes', []); $lengths = $index->getAttribute('lengths', []); $orders = $index->getAttribute('orders', []); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); try { if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { @@ -438,7 +438,7 @@ class Databases extends Action * @param Document $collection * @param Document $index * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject * @return void * @throws Authorization @@ -447,7 +447,7 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void + private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -465,7 +465,7 @@ class Databases extends Action ]); $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); try { if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index e6002bf75f..f286ed4c4c 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -45,7 +45,7 @@ class Deletes extends Action $this ->desc('Deletes worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('deviceForFiles') ->inject('deviceForFunctions') @@ -57,8 +57,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -89,10 +89,10 @@ class Deletes extends Action case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { case DELETE_TYPE_PROJECTS: - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document); + $this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document); break; case DELETE_TYPE_FUNCTIONS: - $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project); + $this->deleteFunction($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project); break; case DELETE_TYPE_DEPLOYMENTS: $this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); @@ -104,10 +104,10 @@ class Deletes extends Action $this->deleteBucket($getProjectDB, $deviceForFiles, $document, $project); break; case DELETE_TYPE_INSTALLATIONS: - $this->deleteInstallation($dbForConsole, $getProjectDB, $document, $project); + $this->deleteInstallation($dbForPlatform, $getProjectDB, $document, $project); break; case DELETE_TYPE_RULES: - $this->deleteRule($dbForConsole, $document, $certificates); + $this->deleteRule($dbForPlatform, $document, $certificates); break; default: Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); @@ -115,7 +115,7 @@ class Deletes extends Action } break; case DELETE_TYPE_TEAM_PROJECTS: - $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $certificates, $document); + $this->deleteProjectsByTeam($dbForPlatform, $getProjectDB, $certificates, $document); break; case DELETE_TYPE_EXECUTIONS: $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); @@ -129,7 +129,7 @@ class Deletes extends Action $this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention); break; case DELETE_TYPE_REALTIME: - $this->deleteRealtimeUsage($dbForConsole, $datetime); + $this->deleteRealtimeUsage($dbForPlatform, $datetime); break; case DELETE_TYPE_SESSIONS: $this->deleteExpiredSessions($project, $getProjectDB); @@ -144,7 +144,7 @@ class Deletes extends Action $this->deleteCacheByDate($project, $getProjectDB, $datetime); break; case DELETE_TYPE_SCHEDULES: - $this->deleteSchedules($dbForConsole, $getProjectDB, $datetime); + $this->deleteSchedules($dbForPlatform, $getProjectDB, $datetime); break; case DELETE_TYPE_TOPIC: $this->deleteTopic($project, $getProjectDB, $document); @@ -164,7 +164,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @param Document|null $document @@ -175,7 +175,7 @@ class Deletes extends Action * @throws Structure * @throws DatabaseException */ - private function deleteSchedules(Database $dbForConsole, callable $getProjectDB, string $datetime): void + private function deleteSchedules(Database $dbForPlatform, callable $getProjectDB, string $datetime): void { $this->listByGroup( 'schedules', @@ -184,12 +184,12 @@ class Deletes extends Action Query::lessThanEqual('resourceUpdatedAt', $datetime), Query::equal('active', [false]), ], - $dbForConsole, - function (Document $document) use ($dbForConsole, $getProjectDB) { - $project = $dbForConsole->getDocument('projects', $document->getAttribute('projectId')); + $dbForPlatform, + function (Document $document) use ($dbForPlatform, $getProjectDB) { + $project = $dbForPlatform->getDocument('projects', $document->getAttribute('projectId')); if ($project->isEmpty()) { - $dbForConsole->deleteDocument('schedules', $document->getId()); + $dbForPlatform->deleteDocument('schedules', $document->getId()); Console::success('Deleted schedule for deleted project ' . $document->getAttribute('projectId')); return; } @@ -213,7 +213,7 @@ class Deletes extends Action } if ($delete) { - $dbForConsole->deleteDocument('schedules', $document->getId()); + $dbForPlatform->deleteDocument('schedules', $document->getId()); Console::success('Deleting schedule for ' . $document->getAttribute('resourceType') . ' ' . $document->getAttribute('resourceId')); } } @@ -394,7 +394,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $hourlyUsageRetentionDatetime * @return void @@ -437,7 +437,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Document $document * @return void * @throws Authorization @@ -447,10 +447,10 @@ class Deletes extends Action * @throws Structure * @throws Exception */ - private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void + private function deleteProjectsByTeam(Database $dbForPlatform, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void { - $projects = $dbForConsole->find('projects', [ + $projects = $dbForPlatform->find('projects', [ Query::equal('teamInternalId', [$document->getInternalId()]) ]); @@ -460,13 +460,13 @@ class Deletes extends Action $deviceForBuilds = getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); $deviceForCache = getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $project); - $dbForConsole->deleteDocument('projects', $project->getId()); + $this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $project); + $dbForPlatform->deleteDocument('projects', $project->getId()); } } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param Device $deviceForFiles * @param Device $deviceForFunctions @@ -478,7 +478,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void + private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { $projectInternalId = $document->getInternalId(); $projectId = $document->getId(); @@ -537,44 +537,44 @@ class Deletes extends Action // Delete Platforms $this->deleteByGroup('platforms', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + ], $dbForPlatform); // Delete project and function rules $this->deleteByGroup('rules', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole, function (Document $document) use ($dbForConsole, $certificates) { - $this->deleteRule($dbForConsole, $document, $certificates); + ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); }); // Delete Keys $this->deleteByGroup('keys', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + ], $dbForPlatform); // Delete Webhooks $this->deleteByGroup('webhooks', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + ], $dbForPlatform); // Delete VCS Installations $this->deleteByGroup('installations', [ Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + ], $dbForPlatform); // Delete VCS Repositories $this->deleteByGroup('repositories', [ Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + ], $dbForPlatform); // Delete VCS comments $this->deleteByGroup('vcsComments', [ Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + ], $dbForPlatform); // Delete Schedules (No projectInternalId in this collection) $this->deleteByGroup('schedules', [ Query::equal('projectId', [$projectId]), - ], $dbForConsole); + ], $dbForPlatform); // Delete metadata table if ($projectTables) { @@ -654,7 +654,7 @@ class Deletes extends Action } /** - * @param database $dbForConsole + * @param database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @return void @@ -670,7 +670,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @return void * @throws Exception|Throwable @@ -688,21 +688,21 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param string $datetime * @return void * @throws Exception */ - private function deleteRealtimeUsage(Database $dbForConsole, string $datetime): void + private function deleteRealtimeUsage(Database $dbForPlatform, string $datetime): void { // Delete Dead Realtime Logs $this->deleteByGroup('realtime', [ Query::lessThan('timestamp', $datetime) - ], $dbForConsole); + ], $dbForPlatform); } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @return void @@ -723,7 +723,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @return void @@ -751,7 +751,7 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project): void + private function deleteFunction(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); @@ -766,8 +766,8 @@ class Deletes extends Action Query::equal('resourceType', ['function']), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('projectInternalId', [$project->getInternalId()]) - ], $dbForConsole, function (Document $document) use ($project, $dbForConsole, $certificates) { - $this->deleteRule($dbForConsole, $document, $certificates); + ], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); }); /** @@ -821,13 +821,13 @@ class Deletes extends Action Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), - ], $dbForConsole, function (Document $document) use ($dbForConsole) { + ], $dbForPlatform, function (Document $document) use ($dbForPlatform) { $providerRepositoryId = $document->getAttribute('providerRepositoryId', ''); $projectInternalId = $document->getAttribute('projectInternalId', ''); $this->deleteByGroup('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + ], $dbForPlatform); }); /** @@ -1049,18 +1049,18 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Document $document rule document * @return void */ - private function deleteRule(Database $dbForConsole, Document $document, CertificatesAdapter $certificates): void + private function deleteRule(Database $dbForPlatform, Document $document, CertificatesAdapter $certificates): void { $domain = $document->getAttribute('domain'); $certificates->deleteCertificate($domain); // Delete certificate document, so Appwrite is aware of change if (isset($document['certificateId'])) { - $dbForConsole->deleteDocument('certificates', $document['certificateId']); + $dbForPlatform->deleteDocument('certificates', $document['certificateId']); } } @@ -1081,21 +1081,21 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param Document $document * @param Document $project * @return void * @throws Exception */ - private function deleteInstallation(Database $dbForConsole, callable $getProjectDB, Document $document, Document $project): void + private function deleteInstallation(Database $dbForPlatform, callable $getProjectDB, Document $document, Document $project): void { $dbForProject = $getProjectDB($project); $this->listByGroup('functions', [ Query::equal('installationInternalId', [$document->getInternalId()]) - ], $dbForProject, function ($function) use ($dbForProject, $dbForConsole) { - $dbForConsole->deleteDocument('repositories', $function->getAttribute('repositoryId')); + ], $dbForProject, function ($function) use ($dbForProject, $dbForPlatform) { + $dbForPlatform->deleteDocument('repositories', $function->getAttribute('repositoryId')); $function = $function ->setAttribute('installationId', '') diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index cd695d09d7..f6af0eb5f2 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -32,7 +32,7 @@ class Migrations extends Action { protected Database $dbForProject; - protected Database $dbForConsole; + protected Database $dbForPlatform; protected Document $project; @@ -52,15 +52,15 @@ class Migrations extends Action ->desc('Migrations worker') ->inject('message') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('logError') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, callable $logError) => $this->action($message, $dbForProject, $dbForConsole, $logError)); + ->callback(fn (Message $message, Database $dbForProject, Database $dbForPlatform, callable $logError) => $this->action($message, $dbForProject, $dbForPlatform, $logError)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, callable $logError): void + public function action(Message $message, Database $dbForProject, Database $dbForPlatform, callable $logError): void { $payload = $message->getPayload() ?? []; @@ -77,7 +77,7 @@ class Migrations extends Action } $this->dbForProject = $dbForProject; - $this->dbForConsole = $dbForConsole; + $this->dbForPlatform = $dbForPlatform; $this->project = $project; $this->logError = $logError; @@ -197,7 +197,7 @@ class Migrations extends Action */ protected function removeAPIKey(Document $apiKey): void { - $this->dbForConsole->deleteDocument('keys', $apiKey->getId()); + $this->dbForPlatform->deleteDocument('keys', $apiKey->getId()); } /** @@ -244,8 +244,8 @@ class Migrations extends Action 'secret' => $generatedSecret, ]); - $this->dbForConsole->createDocument('keys', $key); - $this->dbForConsole->purgeCachedDocument('projects', $project->getId()); + $this->dbForPlatform->createDocument('keys', $key); + $this->dbForPlatform->purgeCachedDocument('projects', $project->getId()); return $key; } @@ -261,7 +261,7 @@ class Migrations extends Action protected function processMigration(Document $migration): void { $project = $this->project; - $projectDocument = $this->dbForConsole->getDocument('projects', $project->getId()); + $projectDocument = $this->dbForPlatform->getDocument('projects', $project->getId()); $tempAPIKey = $this->generateAPIKey($projectDocument); $transfer = $source = $destination = null; diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 88ca7871f2..ba0bdaa6a3 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -31,21 +31,21 @@ class Webhooks extends Action $this ->desc('Webhooks worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForMails') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Mail $queueForMails, Log $log) => $this->action($message, $dbForConsole, $queueForMails, $log)); + ->callback(fn (Message $message, Database $dbForPlatform, Mail $queueForMails, Log $log) => $this->action($message, $dbForPlatform, $queueForMails, $log)); } /** * @param Message $message - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Log $log * @return void * @throws Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Log $log): void + public function action(Message $message, Database $dbForPlatform, Mail $queueForMails, Log $log): void { $this->errors = []; $payload = $message->getPayload() ?? []; @@ -63,7 +63,7 @@ class Webhooks extends Action foreach ($project->getAttribute('webhooks', []) as $webhook) { if (array_intersect($webhook->getAttribute('events', []), $events)) { - $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForConsole, $queueForMails); + $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails); } } @@ -78,11 +78,11 @@ class Webhooks extends Action * @param Document $webhook * @param Document $user * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @return void */ - private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForConsole, Mail $queueForMails): void + private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails): void { if ($webhook->getAttribute('enabled') !== true) { return; @@ -138,8 +138,8 @@ class Webhooks extends Action \curl_close($ch); if (!empty($curlError) || $statusCode >= 400) { - $dbForConsole->increaseDocumentAttribute('webhooks', $webhook->getId(), 'attempts', 1); - $webhook = $dbForConsole->getDocument('webhooks', $webhook->getId()); + $dbForPlatform->increaseDocumentAttribute('webhooks', $webhook->getId(), 'attempts', 1); + $webhook = $dbForPlatform->getDocument('webhooks', $webhook->getId()); $attempts = $webhook->getAttribute('attempts'); $logs = ''; @@ -158,17 +158,17 @@ class Webhooks extends Action if ($attempts >= \intval(System::getEnv('_APP_WEBHOOK_MAX_FAILED_ATTEMPTS', '10'))) { $webhook->setAttribute('enabled', false); - $this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForConsole, $queueForMails); + $this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForMails); } - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $this->errors[] = $logs; } else { $webhook->setAttribute('attempts', 0); // Reset attempts on success - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } @@ -177,20 +177,20 @@ class Webhooks extends Action * @param mixed $statusCode * @param Document $webhook * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @return void */ - public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForConsole, Mail $queueForMails): void + public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Mail $queueForMails): void { - $memberships = $dbForConsole->find('memberships', [ + $memberships = $dbForPlatform->find('memberships', [ Query::equal('teamInternalId', [$project->getAttribute('teamInternalId')]), Query::limit(APP_LIMIT_SUBQUERY) ]); $userIds = array_column(\array_map(fn ($membership) => $membership->getArrayCopy(), $memberships), 'userId'); - $users = $dbForConsole->find('users', [ + $users = $dbForPlatform->find('users', [ Query::equal('$id', $userIds), ]); From b145477114db5f6c5c10e0793aa8bbacfac6cc70 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 12:30:36 +0200 Subject: [PATCH 109/340] payload bug fix --- src/Appwrite/Platform/Workers/Usage.php | 2 +- src/Appwrite/Platform/Workers/UsageDump.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 3f24210cea..cdbb7b5aaa 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -75,7 +75,7 @@ class Usage extends Action } $this->stats[$projectId]['project'] = [ - '$uid' => $project->getId(), + '$id' => $project->getId(), '$internalId' => $project->getInternalId(), 'database' => $project->getAttribute('database'), ]; diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index b5480e1dec..9fbef8f1b8 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -66,9 +66,9 @@ class UsageDump extends Action continue; } - console::log('[' . DateTime::now() . '] ProjectId [' . $project->getInternalId() . '] ReceivedAt [' . $receivedAt . '] ' . $numberOfKeys . ' keys'); - try { + console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getInternalId(). ' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + $dbForProject = $getProjectDB($project); foreach ($stats['keys'] ?? [] as $key => $value) { if ($value == 0) { From 6dcd679412ff2257d864c46391d3afc3dd11c0ec Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 12:34:39 +0200 Subject: [PATCH 110/340] payload bug fix --- src/Appwrite/Platform/Workers/UsageDump.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 9fbef8f1b8..53a42b1a08 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -67,7 +67,7 @@ class UsageDump extends Action } try { - console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getInternalId(). ' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); $dbForProject = $getProjectDB($project); foreach ($stats['keys'] ?? [] as $key => $value) { From ed66e8e41bf6ba0e580b574c1e7e3c29495a554b Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 12:36:34 +0200 Subject: [PATCH 111/340] payload bug fix --- src/Appwrite/Platform/Workers/UsageDump.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 53a42b1a08..3c3ad0d0f3 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -66,9 +66,9 @@ class UsageDump extends Action continue; } - try { - console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + try { $dbForProject = $getProjectDB($project); foreach ($stats['keys'] ?? [] as $key => $value) { if ($value == 0) { From f6157dd2c03216763ba08e1b8e5397a031a867ad Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 16:44:41 +0200 Subject: [PATCH 112/340] payload bug fix --- src/Appwrite/Platform/Workers/UsageDump.php | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 3c3ad0d0f3..1b6d4f81a8 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -57,9 +57,28 @@ class UsageDump extends Action throw new Exception('Missing payload'); } - // TODO: rename both usage workers @shimonewman + foreach ($payload['stats'] ?? [] as $stats) { - $project = new Document($stats['project'] ?? []); + //$project = new Document($stats['project'] ?? []); + + /** + * Start temp bug fallback + */ + $document = $stats['project'] ?? []; + if(!empty($document['$uid'])) { + $document['$id'] = $document['$uid']; + } + + $project = new Document($document); + + if(empty($project->getAttribute('database'))){ + var_dump($stats); + } + + /** + * End temp bug fallback + */ + $numberOfKeys = !empty($stats['keys']) ? count($stats['keys']) : 0; $receivedAt = $stats['receivedAt'] ?? 'NONE'; if ($numberOfKeys === 0) { From 6a28d4eee630ced990b75e3f90052794230bc4d5 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 16:55:14 +0200 Subject: [PATCH 113/340] payload bug fix --- src/Appwrite/Platform/Workers/UsageDump.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 1b6d4f81a8..1fe6b742b8 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -65,13 +65,13 @@ class UsageDump extends Action * Start temp bug fallback */ $document = $stats['project'] ?? []; - if(!empty($document['$uid'])) { + if (!empty($document['$uid'])) { $document['$id'] = $document['$uid']; } $project = new Document($document); - if(empty($project->getAttribute('database'))){ + if (empty($project->getAttribute('database'))) { var_dump($stats); } From dc64fe85e981060465126047eb39ee03371805f6 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 17:46:04 +0200 Subject: [PATCH 114/340] payload bug fix --- src/Appwrite/Platform/Workers/Usage.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index cdbb7b5aaa..5d97e64b38 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -59,7 +59,14 @@ class Usage extends Action throw new Exception('Missing payload'); } - $project = new Document($payload['project'] ?? []); + $document = $payload['project'] ?? []; + + if(empty($document)){ + var_dump($payload); + return; + } + + $project = new Document($document); $projectId = $project->getInternalId(); foreach ($payload['reduce'] ?? [] as $document) { if (empty($document)) { From c5605ac8be2a1c51e5fe0e09760cc95304363b67 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 17:46:27 +0200 Subject: [PATCH 115/340] payload bug fix --- src/Appwrite/Platform/Workers/Usage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 5d97e64b38..eb7b75fd96 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -59,9 +59,9 @@ class Usage extends Action throw new Exception('Missing payload'); } - $document = $payload['project'] ?? []; + $document = $payload['project'] ?? []; - if(empty($document)){ + if (empty($document)) { var_dump($payload); return; } From 158954df0bbd66b2d84a4639e09bff0a3d39ceaf Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 18:55:45 +0200 Subject: [PATCH 116/340] Usage payload debug --- src/Appwrite/Platform/Workers/Usage.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index eb7b75fd96..98b2ea32c7 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -63,7 +63,6 @@ class Usage extends Action if (empty($document)) { var_dump($payload); - return; } $project = new Document($document); From a12b758658e32d01df7e1a2c5fa54b58b5855bce Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:11:22 +0000 Subject: [PATCH 117/340] feat: upgrade assistant to 0.6,0 --- app/controllers/api/console.php | 8 ++++++-- docker-compose.yml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index eeb823a3d3..b7c7c05641 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -69,11 +69,15 @@ App::post('/v1/console/assistant') ->label('abuse-limit', 15) ->label('abuse-key', 'userId:{userId}') ->param('prompt', '', new Text(2000), 'Prompt. A string containing questions asked to the AI assistant.') + ->param('systemPrompt', '', new Text(2000), 'System Prompt. A string containing context to help the AI assistant provide better responses.') ->inject('response') - ->action(function (string $prompt, Response $response) { + ->action(function (string $prompt, string $systemPrompt, Response $response) { $ch = curl_init('http://appwrite-assistant:3003/'); $responseHeaders = []; - $query = json_encode(['prompt' => $prompt]); + $query = json_encode([ + 'prompt' => $prompt, + 'systemPrompt' => $systemPrompt, + ]); $headers = ['accept: text/event-stream']; $handleEvent = function ($ch, $data) use ($response) { $response->chunk($data); diff --git a/docker-compose.yml b/docker-compose.yml index f9a79ee84d..9652767a1f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -868,7 +868,7 @@ services: appwrite-assistant: container_name: appwrite-assistant - image: appwrite/assistant:0.5.0 + image: appwrite/assistant:0.6.0 networks: - appwrite environment: From 717b06950ec32e12928c4e2ceb80e8e5d400dbec Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 20:20:47 +0200 Subject: [PATCH 118/340] Usage payload debug --- src/Appwrite/Platform/Workers/Usage.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 98b2ea32c7..855f9c1ebc 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -60,12 +60,13 @@ class Usage extends Action } $document = $payload['project'] ?? []; + $project = new Document($document); - if (empty($document)) { + if (empty($project->getAttribute('database'))) { + var_dump(1); var_dump($payload); } - $project = new Document($document); $projectId = $project->getInternalId(); foreach ($payload['reduce'] ?? [] as $document) { if (empty($document)) { @@ -80,6 +81,11 @@ class Usage extends Action ); } + if (empty($project->getAttribute('database'))) { + var_dump(2); + var_dump($payload); + } + $this->stats[$projectId]['project'] = [ '$id' => $project->getId(), '$internalId' => $project->getInternalId(), From 6a9eeeb370f4dfb2b4ac7757dafc45b23f124e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 19:39:24 +0100 Subject: [PATCH 119/340] Add createFunction abuse labels --- app/controllers/api/functions.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 003efbad03..25e8886a46 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -141,6 +141,9 @@ App::post('/v1/functions') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'function.create') ->label('audits.resource', 'function/{response.$id}') + ->label('abuse-key', 'projectId:{projectId}') + ->label('abuse-limit', 50) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT * 24) // 1 day ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'functions') ->label('sdk.method', 'create') From eb2c3cd73fb15a8af98ad6978e1e3350da94c732 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:55:38 +0000 Subject: [PATCH 120/340] chore: platform bump --- app/config/platforms.php | 8 ++--- composer.lock | 70 ++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index e54fb0a073..1470bd1364 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '16.0.2', + 'version' => '16.1.0', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '13.0.0', + 'version' => '13.1.0', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -77,7 +77,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '7.0.0', + 'version' => '7.1.0', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -112,7 +112,7 @@ return [ [ 'key' => 'android', 'name' => 'Android', - 'version' => '6.0.0', + 'version' => '6.1.0', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, diff --git a/composer.lock b/composer.lock index ee947d27f0..986a534435 100644 --- a/composer.lock +++ b/composer.lock @@ -1237,16 +1237,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" }, "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/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", "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": "2024-11-16T04:32:30+00:00" }, { "name": "open-telemetry/context", @@ -2453,23 +2453,23 @@ }, { "name": "symfony/http-client", - "version": "v7.2.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" }, "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/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", "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.1" }, "funding": [ { @@ -2544,20 +2544,20 @@ "type": "tidelift" } ], - "time": "2024-11-29T08:22:02+00:00" + "time": "2024-12-07T08:50:44+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": { @@ -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": { @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.25", + "version": "0.39.26", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" + "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c" }, "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/39768deacb4913f93548c46fa0149c3fadc62d0c", + "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c", "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.26" }, - "time": "2024-11-08T10:16:34+00:00" + "time": "2024-12-12T10:51:34+00:00" }, { "name": "doctrine/annotations", @@ -7576,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": { @@ -7649,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": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/filesystem", From bc38fd26407931d0a6a34c394569039830cc718d Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:04:31 +0000 Subject: [PATCH 121/340] fix: hide system prompt --- app/controllers/api/console.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index b7c7c05641..eeb823a3d3 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -69,15 +69,11 @@ App::post('/v1/console/assistant') ->label('abuse-limit', 15) ->label('abuse-key', 'userId:{userId}') ->param('prompt', '', new Text(2000), 'Prompt. A string containing questions asked to the AI assistant.') - ->param('systemPrompt', '', new Text(2000), 'System Prompt. A string containing context to help the AI assistant provide better responses.') ->inject('response') - ->action(function (string $prompt, string $systemPrompt, Response $response) { + ->action(function (string $prompt, Response $response) { $ch = curl_init('http://appwrite-assistant:3003/'); $responseHeaders = []; - $query = json_encode([ - 'prompt' => $prompt, - 'systemPrompt' => $systemPrompt, - ]); + $query = json_encode(['prompt' => $prompt]); $headers = ['accept: text/event-stream']; $handleEvent = function ($ch, $data) use ($response) { $response->chunk($data); From 177fd92094d68b2f07b7fc884a882f7514c23a92 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 21:20:55 +0200 Subject: [PATCH 122/340] Usage payload debug --- src/Appwrite/Platform/Workers/Usage.php | 6 +----- src/Appwrite/Platform/Workers/UsageDump.php | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 855f9c1ebc..8199fe73a7 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -63,8 +63,8 @@ class Usage extends Action $project = new Document($document); if (empty($project->getAttribute('database'))) { - var_dump(1); var_dump($payload); + return; } $projectId = $project->getInternalId(); @@ -81,10 +81,6 @@ class Usage extends Action ); } - if (empty($project->getAttribute('database'))) { - var_dump(2); - var_dump($payload); - } $this->stats[$projectId]['project'] = [ '$id' => $project->getId(), diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 1fe6b742b8..78235ce7e9 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -71,10 +71,6 @@ class UsageDump extends Action $project = new Document($document); - if (empty($project->getAttribute('database'))) { - var_dump($stats); - } - /** * End temp bug fallback */ From a18472507b572dcf704b1929b88d8663ddb86653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 20:45:49 +0100 Subject: [PATCH 123/340] Add createFunction abuse check + fix abuse --- app/controllers/api/functions.php | 31 ++++++++++++++++++++++++++++--- composer.lock | 14 +++++++------- docker-compose.yml | 1 + 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 25e8886a46..b263535777 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -23,6 +23,8 @@ use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model\Rule; use Executor\Executor; use MaxMind\Db\Reader; +use Utopia\Abuse\Abuse; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -141,9 +143,6 @@ App::post('/v1/functions') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'function.create') ->label('audits.resource', 'function/{response.$id}') - ->label('abuse-key', 'projectId:{projectId}') - ->label('abuse-limit', 50) - ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT * 24) // 1 day ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'functions') ->label('sdk.method', 'create') @@ -190,6 +189,32 @@ App::post('/v1/functions') ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; + // Temporary abuse check + $abuseKey = "projectId:{projectId},url:{url}"; + $abuseLimit = 5; + $abuseTime = 86400; // 1 day + + $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); + $timeLimit + ->setParam('{projectId}', $project->getId()) + ->setParam('{url}', '/v1/functions'); + + $abuse = new Abuse($timeLimit); + $remaining = $timeLimit->remaining(); + $limit = $timeLimit->limit(); + $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $abuseTime; + + $response + ->addHeader('X-RateLimit-Limit', $limit) + ->addHeader('X-RateLimit-Remaining', $remaining) + ->addHeader('X-RateLimit-Reset', $time); + + $enabled = System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; + if($enabled && $abuse->check()) { + throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); + } + // End of temporary abuse check + $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); if (!empty($allowList) && !\in_array($runtime, $allowList)) { diff --git a/composer.lock b/composer.lock index ee947d27f0..732bafd219 100644 --- a/composer.lock +++ b/composer.lock @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.1", + "version": "0.43.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa" + "reference": "374536b86d8d39066960a7da161d444a099bbc56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/e404c21e8dcf6a310bc83cf1d74e716b105598fa", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", + "reference": "374536b86d8d39066960a7da161d444a099bbc56", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.53.200" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.1" + "source": "https://github.com/utopia-php/abuse/tree/0.43.2" }, - "time": "2024-10-23T04:29:12+00:00" + "time": "2024-12-12T19:43:24+00:00" }, { "name": "utopia-php/analytics", diff --git a/docker-compose.yml b/docker-compose.yml index f9a79ee84d..db5416d2b5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,6 +83,7 @@ services: - ./public:/usr/src/code/public - ./src:/usr/src/code/src - ./dev:/usr/src/code/dev + - ./vendor/utopia-php/abuse:/usr/src/code/vendor/utopia-php/abuse depends_on: - mariadb - redis From 9c4d0f2a79a6f6497c1761f9017f8780be19fdf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 20:48:28 +0100 Subject: [PATCH 124/340] Leftover --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index db5416d2b5..f9a79ee84d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,7 +83,6 @@ services: - ./public:/usr/src/code/public - ./src:/usr/src/code/src - ./dev:/usr/src/code/dev - - ./vendor/utopia-php/abuse:/usr/src/code/vendor/utopia-php/abuse depends_on: - mariadb - redis From 04139d690181f6f4bb08883005ad8b8d756d2cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 20:52:31 +0100 Subject: [PATCH 125/340] Linter fix --- app/controllers/api/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index b263535777..76916f2770 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -210,7 +210,7 @@ App::post('/v1/functions') ->addHeader('X-RateLimit-Reset', $time); $enabled = System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; - if($enabled && $abuse->check()) { + if ($enabled && $abuse->check()) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); } // End of temporary abuse check From 01019f505541897b07a4246385887ca225b4de11 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 12 Dec 2024 21:54:59 +0200 Subject: [PATCH 126/340] Usage payload debug --- src/Appwrite/Platform/Workers/UsageDump.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 78235ce7e9..3e50ba0363 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -71,6 +71,10 @@ class UsageDump extends Action $project = new Document($document); + if (empty($project->getAttribute('database'))) { + continue; + } + /** * End temp bug fallback */ From ab7ea056e641b42153d9bc41260903bddea492ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 21:00:04 +0100 Subject: [PATCH 127/340] Increase limit --- app/controllers/api/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 76916f2770..395069bc02 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -191,7 +191,7 @@ App::post('/v1/functions') // Temporary abuse check $abuseKey = "projectId:{projectId},url:{url}"; - $abuseLimit = 5; + $abuseLimit = 50; $abuseTime = 86400; // 1 day $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); From 8b3f09a981b320a180c5946e04b97aca2b67e257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 21:10:22 +0100 Subject: [PATCH 128/340] Env var for function abuse limit --- .env | 1 + app/controllers/api/functions.php | 2 +- docker-compose.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.env b/.env index 2470c786b1..8f7d7996e7 100644 --- a/.env +++ b/.env @@ -109,3 +109,4 @@ _APP_MESSAGE_EMAIL_TEST_DSN= _APP_MESSAGE_PUSH_TEST_DSN= _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default +_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 395069bc02..d473f60a0b 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -191,7 +191,7 @@ App::post('/v1/functions') // Temporary abuse check $abuseKey = "projectId:{projectId},url:{url}"; - $abuseLimit = 50; + $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); $abuseTime = 86400; // 1 day $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); diff --git a/docker-compose.yml b/docker-compose.yml index f9a79ee84d..e78af8b307 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,6 +195,7 @@ services: - _APP_DATABASE_SHARED_TABLES - _APP_DATABASE_SHARED_TABLES_V1 - _APP_DATABASE_SHARED_NAMESPACE + - _APP_FUNCTIONS_CREATION_ABUSE_LIMIT appwrite-console: <<: *x-logging From 905b4938a495e22b481170049b37c7f3d205d9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Thu, 12 Dec 2024 20:55:33 +0000 Subject: [PATCH 129/340] Fix failing test --- app/controllers/api/functions.php | 43 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d473f60a0b..5934258037 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -190,30 +190,33 @@ App::post('/v1/functions') $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check - $abuseKey = "projectId:{projectId},url:{url}"; - $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); - $abuseTime = 86400; // 1 day + $abuseCheck = function () use ($project, $dbForProject, $response) { + $abuseKey = "projectId:{projectId},url:{url}"; + $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); + $abuseTime = 86400; // 1 day - $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); - $timeLimit - ->setParam('{projectId}', $project->getId()) - ->setParam('{url}', '/v1/functions'); + $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); + $timeLimit + ->setParam('{projectId}', $project->getId()) + ->setParam('{url}', '/v1/functions'); - $abuse = new Abuse($timeLimit); - $remaining = $timeLimit->remaining(); - $limit = $timeLimit->limit(); - $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $abuseTime; + $abuse = new Abuse($timeLimit); + $remaining = $timeLimit->remaining(); + $limit = $timeLimit->limit(); + $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $abuseTime; - $response - ->addHeader('X-RateLimit-Limit', $limit) - ->addHeader('X-RateLimit-Remaining', $remaining) - ->addHeader('X-RateLimit-Reset', $time); + $response + ->addHeader('X-RateLimit-Limit', $limit) + ->addHeader('X-RateLimit-Remaining', $remaining) + ->addHeader('X-RateLimit-Reset', $time); - $enabled = System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; - if ($enabled && $abuse->check()) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); - } - // End of temporary abuse check + $enabled = System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; + if ($enabled && $abuse->check()) { + throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); + } + }; + + $abuseCheck(); $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); From 830ad99111c854748d27effadc5e2edec61553d7 Mon Sep 17 00:00:00 2001 From: Fabian Gruber <fabian@appwrite.io> Date: Mon, 2 Dec 2024 10:47:17 +0100 Subject: [PATCH 130/340] chore: add audit labels to project resources --- app/controllers/api/projects.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 388c9e22ea..56e2b7900f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -61,6 +61,7 @@ App::post('/v1/projects') ->desc('Create project') ->groups(['api', 'projects']) ->label('audits.event', 'projects.create') + ->label('audits.resource', 'project/{response.$id}') ->label('scope', 'projects.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'projects') @@ -382,6 +383,8 @@ App::patch('/v1/projects/:projectId') ->desc('Update project') ->groups(['api', 'projects']) ->label('scope', 'projects.write') + ->label('audits.event', 'projects.update') + ->label('audits.resource', 'project/{request.projectId}') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'projects') ->label('sdk.method', 'update') @@ -996,6 +999,7 @@ App::delete('/v1/projects/:projectId') ->desc('Delete project') ->groups(['api', 'projects']) ->label('audits.event', 'projects.delete') + ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'projects.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'projects') @@ -1529,6 +1533,7 @@ App::post('/v1/projects/:projectId/platforms') ->desc('Create platform') ->groups(['api', 'projects']) ->label('audits.event', 'platforms.create') + ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'platforms.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'projects') @@ -1693,6 +1698,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->desc('Delete platform') ->groups(['api', 'projects']) ->label('audits.event', 'platforms.delete') + ->label('audits.resource', 'project/{request.projectId}/platform/${request.platformId}') ->label('scope', 'platforms.write') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'projects') From 515b5904b849136ff755a4c936cb328c1834e4f6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 10 Dec 2024 11:34:51 +0000 Subject: [PATCH 131/340] update project accessed at from router --- app/controllers/general.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 32cc68fecf..2c43116c10 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -91,6 +91,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $project = Authorization::skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); + + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + } + } + if (array_key_exists('proxy', $project->getAttribute('services', []))) { $status = $project->getAttribute('services', [])['proxy']; if (!$status) { From ab4a4441545ac30517610797e1adc0274103f195 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 10 Dec 2024 11:13:09 +0000 Subject: [PATCH 132/340] Fix: project accessed at on workers --- app/worker.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/worker.php b/app/worker.php index 2c7d8acb22..6fdb49d35a 100644 --- a/app/worker.php +++ b/app/worker.php @@ -374,6 +374,20 @@ try { $worker = $platform->getWorker(); +$worker + ->init() + ->inject('project') + ->inject('dbForConsole') + ->action(function (Document $project, Database $dbForConsole) { + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + } + } + }); + $worker ->shutdown() ->inject('pools') From a24dc7903648671e0a3d515dde9bd9cec85e4581 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:36:02 +0000 Subject: [PATCH 133/340] chore: fix endpoint --- app/controllers/api/console.php | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index eeb823a3d3..1b307b1d14 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -71,7 +71,7 @@ App::post('/v1/console/assistant') ->param('prompt', '', new Text(2000), 'Prompt. A string containing questions asked to the AI assistant.') ->inject('response') ->action(function (string $prompt, Response $response) { - $ch = curl_init('http://appwrite-assistant:3003/'); + $ch = curl_init('http://appwrite-assistant:3003/v1/models/assistant/prompt'); $responseHeaders = []; $query = json_encode(['prompt' => $prompt]); $headers = ['accept: text/event-stream']; diff --git a/docker-compose.yml b/docker-compose.yml index 3bdbd969b3..2fb19f7126 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -869,7 +869,7 @@ services: appwrite-assistant: container_name: appwrite-assistant - image: appwrite/assistant:0.6.0 + image: appwrite/assistant:0.7.0 networks: - appwrite environment: From 396faa56c2cc58b6aee2ffebb412eb25535da716 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 08:21:38 +0530 Subject: [PATCH 134/340] chore: initial commit --- app/controllers/api/projects.php | 16 +--- app/controllers/shared/api.php | 7 +- app/http.php | 7 -- app/init.php | 15 ++++ app/realtime.php | 8 +- composer.lock | 90 +++++++++++------------ src/Appwrite/Platform/Workers/Deletes.php | 7 +- 7 files changed, 72 insertions(+), 78 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 92d3103293..06723f4583 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -16,7 +16,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\Redis\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; @@ -229,9 +229,6 @@ App::post('/v1/projects') if ($create || $projectTables) { $audit = new Audit($dbForProject); $audit->setup(); - - $abuse = new TimeLimit('', 0, 1, $dbForProject); - $abuse->setup(); } if (!$create && $sharedTablesV1) { @@ -245,17 +242,6 @@ App::post('/v1/projects') 'indexes' => $indexes, 'documentSecurity' => true ])); - - $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); - $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); - $dbForProject->createDocument(Database::METADATA, new Document([ - '$id' => ID::custom('abuse'), - '$permissions' => [Permission::create(Role::any())], - 'name' => 'abuse', - 'attributes' => $attributes, - 'indexes' => $indexes, - 'documentSecurity' => true - ])); } if ($create || $sharedTablesV1) { diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 91883b0895..ecac7507ba 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -19,7 +19,7 @@ use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\Redis\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -420,8 +420,9 @@ App::init() ->inject('queueForBuilds') ->inject('queueForUsage') ->inject('dbForProject') + ->inject('redis') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, Redis $redis, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -444,7 +445,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); + $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $redis); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) diff --git a/app/http.php b/app/http.php index c4e48a7f69..22ac72227e 100644 --- a/app/http.php +++ b/app/http.php @@ -10,10 +10,8 @@ use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; use Swoole\Process; use Swoole\Table; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; -use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; @@ -200,11 +198,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $audit->setup(); } - if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit("", 0, 1, $dbForConsole); - $adapter->setup(); - } - /** @var array $collections */ $collections = Config::getParam('collections', []); $consoleCollections = $collections['console']; diff --git a/app/init.php b/app/init.php index 30ece74553..8d478d1949 100644 --- a/app/init.php +++ b/app/init.php @@ -1531,6 +1531,21 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); +App::setResource('redis', function (Group $pools) { + $list = Config::getParam('pools-cache', []); + $adapters = []; + + foreach ($list as $value) { + $adapters[] = $pools + ->get($value) + ->pop() + ->getResource() + ; + } + + return new Sharding($adapters); +}, ['pools']); + App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/app/realtime.php b/app/realtime.php index 03eaa53bcc..97937c44fc 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\Redis\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -481,7 +481,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $dbForProject = getProjectDB($project); + $cache = $app->getResource('cache'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -490,7 +490,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject); + $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $cache); $timeLimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); @@ -593,7 +593,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database); + $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $cache); $timeLimit ->setParam('{connection}', $connection) diff --git a/composer.lock b/composer.lock index ee947d27f0..37a5c81436 100644 --- a/composer.lock +++ b/composer.lock @@ -1237,16 +1237,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" }, "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/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", "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": "2024-11-16T04:32:30+00:00" }, { "name": "open-telemetry/context", @@ -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": { @@ -2453,23 +2453,23 @@ }, { "name": "symfony/http-client", - "version": "v7.2.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" }, "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/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", "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.1" }, "funding": [ { @@ -2544,20 +2544,20 @@ "type": "tidelift" } ], - "time": "2024-11-29T08:22:02+00:00" + "time": "2024-12-07T08:50:44+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": { @@ -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": { @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.1", + "version": "0.43.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa" + "reference": "374536b86d8d39066960a7da161d444a099bbc56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/e404c21e8dcf6a310bc83cf1d74e716b105598fa", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", + "reference": "374536b86d8d39066960a7da161d444a099bbc56", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.53.200" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.1" + "source": "https://github.com/utopia-php/abuse/tree/0.43.2" }, - "time": "2024-10-23T04:29:12+00:00" + "time": "2024-12-12T19:43:24+00:00" }, { "name": "utopia-php/analytics", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.25", + "version": "0.39.26", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" + "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c" }, "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/39768deacb4913f93548c46fa0149c3fadc62d0c", + "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c", "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.26" }, - "time": "2024-11-08T10:16:34+00:00" + "time": "2024-12-12T10:51:34+00:00" }, { "name": "doctrine/annotations", @@ -7576,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": { @@ -7649,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": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/filesystem", diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index e6002bf75f..b1c8c90051 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -8,7 +8,7 @@ use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\Redis\TimeLimit; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -494,8 +494,7 @@ class Deletes extends Action $projectCollectionIds = [ ...\array_keys(Config::getParam('collections', [])['projects']), - Audit::COLLECTION, - TimeLimit::COLLECTION, + Audit::COLLECTION ]; $limit = \count($projectCollectionIds) + 25; @@ -712,7 +711,7 @@ class Deletes extends Action { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); - $timeLimit = new TimeLimit("", 0, 1, $dbForProject); + $timeLimit = new TimeLimit("", 0, 1, $cache); $abuse = new Abuse($timeLimit); try { From ee05f3d3bc449e670f21fd9f28a0de9b7dc07596 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 09:49:31 +0530 Subject: [PATCH 135/340] feat: migrate to redis abuse --- .editorconfig | 0 .env | 2 +- app/controllers/api/users.php | 1 + app/controllers/shared/api.php | 6 ++--- app/init.php | 32 +++++++++++------------ app/realtime.php | 27 ++++++++++++++++--- src/Appwrite/Platform/Workers/Deletes.php | 14 +++++----- 7 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.env b/.env index 2470c786b1..6145411c94 100644 --- a/.env +++ b/.env @@ -15,7 +15,7 @@ _APP_SYSTEM_TEAM_EMAIL=team@appwrite.io _APP_EMAIL_SECURITY=security@appwrite.io _APP_EMAIL_CERTIFICATES=certificates@appwrite.io _APP_SYSTEM_RESPONSE_FORMAT= -_APP_OPTIONS_ABUSE=disabled +_APP_OPTIONS_ABUSE=enabled _APP_OPTIONS_ROUTER_PROTECTION=disabled _APP_OPTIONS_FORCE_HTTPS=disabled _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bdb24572eb..1e65c84d7a 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -188,6 +188,7 @@ App::post('/v1/users') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'create') + ->label('abuse-limit', 10) ->label('sdk.description', '/docs/references/users/create-user.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index ecac7507ba..c13d7e0684 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -422,7 +422,7 @@ App::init() ->inject('dbForProject') ->inject('redis') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, Redis $redis, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, \Redis $redis, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -487,8 +487,8 @@ App::init() if ( $enabled // Abuse is enabled - && !$isAppUser // User is not API key - && !$isPrivilegedUser // User is not an admin + // && !$isAppUser // User is not API key + // && !$isPrivilegedUser // User is not an admin && $abuse->check() // Route is rate-limited ) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); diff --git a/app/init.php b/app/init.php index 8d478d1949..a9888e29f5 100644 --- a/app/init.php +++ b/app/init.php @@ -853,31 +853,31 @@ $register->set('pools', function () { $connections = [ 'console' => [ 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), + 'dsns' => $fallbackForDB, 'multiple' => false, 'schemes' => ['mariadb', 'mysql'], ], 'database' => [ 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), + 'dsns' => $fallbackForDB, 'multiple' => true, 'schemes' => ['mariadb', 'mysql'], ], 'queue' => [ 'type' => 'queue', - 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => false, 'schemes' => ['redis'], ], 'pubsub' => [ 'type' => 'pubsub', - 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => false, 'schemes' => ['redis'], ], 'cache' => [ 'type' => 'cache', - 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => true, 'schemes' => ['redis'], ], @@ -949,12 +949,12 @@ $register->set('pools', function () { }); }, 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new Redis(); + $redis = new \Redis(); @$redis->pconnect($dsnHost, (int)$dsnPort); if ($dsnPass) { $redis->auth($dsnPass); } - $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); return $redis; }, @@ -1532,18 +1532,18 @@ App::setResource('cache', function (Group $pools) { }, ['pools']); App::setResource('redis', function (Group $pools) { - $list = Config::getParam('pools-cache', []); - $adapters = []; + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); - foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource() - ; + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); - return new Sharding($adapters); + return $redis; }, ['pools']); App::setResource('deviceForLocal', function () { diff --git a/app/realtime.php b/app/realtime.php index 97937c44fc..f55ae30f3e 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -138,6 +138,26 @@ if (!function_exists('getCache')) { } } +// Allows overriding +if (!function_exists('getRedis')) { + function getRedis(): \Redis + { + + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; + } +} + if (!function_exists('getRealtime')) { function getRealtime(): Realtime { @@ -481,7 +501,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $cache = $app->getResource('cache'); + $redis = $app->getResource('redis'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -490,7 +510,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $cache); + $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $redis); $timeLimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); @@ -593,7 +613,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $cache); + $redis = getRedis(); + $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $redis); $timeLimit ->setParam('{connection}', $connection) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index b1c8c90051..e217ebbf7b 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -47,6 +47,7 @@ class Deletes extends Action ->inject('message') ->inject('dbForConsole') ->inject('getProjectDB') + ->inject('redis') ->inject('deviceForFiles') ->inject('deviceForFunctions') ->inject('deviceForBuilds') @@ -57,8 +58,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForConsole, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForConsole, $getProjectDB, $redis, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +67,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForConsole, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -126,7 +127,7 @@ class Deletes extends Action } break; case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention); + $this->deleteAbuseLogs($project, $redis, $abuseRetention); break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForConsole, $datetime); @@ -707,11 +708,10 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, \Redis $redis, string $abuseRetention): void { $projectId = $project->getId(); - $dbForProject = $getProjectDB($project); - $timeLimit = new TimeLimit("", 0, 1, $cache); + $timeLimit = new TimeLimit("", 0, 1, $redis); $abuse = new Abuse($timeLimit); try { From 06c09503df70bb2e5677cf4d390864fc4f718ce0 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 04:27:28 +0000 Subject: [PATCH 136/340] update project rsource --- app/worker.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/worker.php b/app/worker.php index 6fdb49d35a..06dc4c44d8 100644 --- a/app/worker.php +++ b/app/worker.php @@ -62,7 +62,13 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $project; } - return $dbForPlatform->getDocument('projects', $project->getId()); + // NOT all workers need valid DB config so we return empty if this fails + try { + return $dbForPlatform->getDocument('projects', $project->getId()); + } catch (\Throwable $e) { + return new Document([]); + } + }, ['message', 'dbForPlatform']); Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { From e8cea7034693f9981af427a38c15876b43084035 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:00:28 +0530 Subject: [PATCH 137/340] feat: cleanup --- .editorconfig | 0 app/controllers/api/users.php | 1 - 2 files changed, 1 deletion(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 1e65c84d7a..bdb24572eb 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -188,7 +188,6 @@ App::post('/v1/users') ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'users') ->label('sdk.method', 'create') - ->label('abuse-limit', 10) ->label('sdk.description', '/docs/references/users/create-user.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) From 67996a8a14938b67c0a28f429abe0087d0773af3 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:00:45 +0530 Subject: [PATCH 138/340] feat: cleanup --- app/controllers/shared/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index c13d7e0684..af2f6a6e7c 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -487,8 +487,8 @@ App::init() if ( $enabled // Abuse is enabled - // && !$isAppUser // User is not API key - // && !$isPrivilegedUser // User is not an admin + && !$isAppUser // User is not API key + && !$isPrivilegedUser // User is not an admin && $abuse->check() // Route is rate-limited ) { throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); From 801f311faf57315ee5cdd310b5cb35c59f9503c9 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:08:16 +0530 Subject: [PATCH 139/340] feat: cleanup --- app/realtime.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/realtime.php b/app/realtime.php index f55ae30f3e..b9ea7c4765 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -142,7 +142,6 @@ if (!function_exists('getCache')) { if (!function_exists('getRedis')) { function getRedis(): \Redis { - $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); $port = System::getEnv('_APP_REDIS_PORT', 6379); $pass = System::getEnv('_APP_REDIS_PASS', ''); From b55a01c5b339d8bf838391571e92e674d86c092c Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:12:17 +0530 Subject: [PATCH 140/340] chore: linter --- app/controllers/api/projects.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 8411ac2a1f..cbda6ad544 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -16,7 +16,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; -use Utopia\Abuse\Adapters\Redis\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; From cc867e285971f40a996864832b4cfbac95f6f746 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:23:09 +0530 Subject: [PATCH 141/340] chore: rename variable --- app/init.php | 4 ++-- src/Appwrite/Platform/Workers/Deletes.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/init.php b/app/init.php index 2d01597bc1..056e8ed3d5 100644 --- a/app/init.php +++ b/app/init.php @@ -1531,7 +1531,7 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); -App::setResource('redis', function (Group $pools) { +App::setResource('redis', function () { $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); $port = System::getEnv('_APP_REDIS_PORT', 6379); $pass = System::getEnv('_APP_REDIS_PASS', ''); @@ -1544,7 +1544,7 @@ App::setResource('redis', function (Group $pools) { $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); return $redis; -}, ['pools']); +}); App::setResource('deviceForLocal', function () { return new Local(); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index bbc04cec02..6fa65ec842 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -58,8 +58,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForConsole, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForConsole, $getProjectDB, $redis, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $redis, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -67,7 +67,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; From 52ac358f539757e8cc92ea3fe550a98bc0c9288e Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Tue, 17 Dec 2024 10:23:52 +0530 Subject: [PATCH 142/340] chore: rename variable --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index e998cabee1..8f7d7996e7 100644 --- a/.env +++ b/.env @@ -15,7 +15,7 @@ _APP_SYSTEM_TEAM_EMAIL=team@appwrite.io _APP_EMAIL_SECURITY=security@appwrite.io _APP_EMAIL_CERTIFICATES=certificates@appwrite.io _APP_SYSTEM_RESPONSE_FORMAT= -_APP_OPTIONS_ABUSE=enabled +_APP_OPTIONS_ABUSE=disabled _APP_OPTIONS_ROUTER_PROTECTION=disabled _APP_OPTIONS_FORCE_HTTPS=disabled _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled From 6372cf59ccbbe4b20530397c3ef25ce881fecb5b Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 17 Dec 2024 11:54:50 +0000 Subject: [PATCH 143/340] chore: composer --- composer.json | 2 +- composer.lock | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 512e203a5e..fdbf2b4514 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.39.*", + "appwrite/sdk-generator": "0.39.27", "phpunit/phpunit": "9.5.20", "swoole/ide-helper": "5.1.2", "textalk/websocket": "1.5.7", diff --git a/composer.lock b/composer.lock index 986a534435..ac77c575ec 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": "fae350df93342992edd8f639948e1570", + "content-hash": "35d6e3f5c403194ad7969d48dc4cbdf5", "packages": [ { "name": "adhocore/jwt", @@ -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": { @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.1", + "version": "0.43.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa" + "reference": "374536b86d8d39066960a7da161d444a099bbc56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/e404c21e8dcf6a310bc83cf1d74e716b105598fa", - "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", + "reference": "374536b86d8d39066960a7da161d444a099bbc56", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.53.200" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.1" + "source": "https://github.com/utopia-php/abuse/tree/0.43.2" }, - "time": "2024-10-23T04:29:12+00:00" + "time": "2024-12-12T19:43:24+00:00" }, { "name": "utopia-php/analytics", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.26", + "version": "0.39.27", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c" + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/39768deacb4913f93548c46fa0149c3fadc62d0c", - "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/27d8ecde30e40cbfe1124cc0430c406d3e144849", + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849", "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.26" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.27" }, - "time": "2024-12-12T10:51:34+00:00" + "time": "2024-12-16T11:32:02+00:00" }, { "name": "doctrine/annotations", From 47785d9c4de9a53f534192bd7e6563ec71bc9f3b Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 17 Dec 2024 11:58:25 +0000 Subject: [PATCH 144/340] docs: update --- .../1.6.x/client-graphql/examples/account/create-push-target.md | 1 + docs/examples/1.6.x/client-graphql/examples/account/create.md | 1 + docs/examples/1.6.x/client-graphql/examples/account/get.md | 1 + .../1.6.x/client-graphql/examples/account/update-email.md | 1 + .../1.6.x/client-graphql/examples/account/update-m-f-a.md | 1 + .../client-graphql/examples/account/update-mfa-authenticator.md | 1 + .../1.6.x/client-graphql/examples/account/update-name.md | 1 + .../1.6.x/client-graphql/examples/account/update-password.md | 1 + .../1.6.x/client-graphql/examples/account/update-phone.md | 1 + .../1.6.x/client-graphql/examples/account/update-prefs.md | 1 + .../1.6.x/client-graphql/examples/account/update-push-target.md | 1 + .../1.6.x/client-graphql/examples/account/update-status.md | 1 + .../1.6.x/client-graphql/examples/messaging/create-subscriber.md | 1 + 13 files changed, 13 insertions(+) diff --git a/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md b/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md index 8a0fad387c..63802a782e 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md @@ -12,5 +12,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/create.md b/docs/examples/1.6.x/client-graphql/examples/account/create.md index 3f8e3c3cf7..0d39394a3d 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/create.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/create.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/get.md b/docs/examples/1.6.x/client-graphql/examples/account/get.md index e4db8f0e41..f4f07c187f 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/get.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/get.md @@ -28,6 +28,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-email.md b/docs/examples/1.6.x/client-graphql/examples/account/update-email.md index b207bad4bb..c879e24a43 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-email.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md b/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md index d2cd3d6ae5..787c2e0860 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md index c74062c7d4..9cfe9150be 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-name.md b/docs/examples/1.6.x/client-graphql/examples/account/update-name.md index 850b5760a0..8ba2c99d9c 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-name.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-name.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-password.md b/docs/examples/1.6.x/client-graphql/examples/account/update-password.md index 5904da0842..f3619a10d2 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-password.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md b/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md index 408a203300..adecb71168 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md b/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md index 40db7b43db..57280247e4 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md b/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md index 059702dc97..3c402cdf12 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md @@ -11,5 +11,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-status.md b/docs/examples/1.6.x/client-graphql/examples/account/update-status.md index aca8c098e7..c17f556842 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-status.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-status.md @@ -28,6 +28,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md index b2712ebb48..bab53612b7 100644 --- a/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md @@ -17,6 +17,7 @@ mutation { providerId providerType identifier + expired } userId userName From c7713f58dd4b0fc33f4d083a183d5ea925ac1233 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 13:52:58 +0000 Subject: [PATCH 145/340] remove worker hook --- app/worker.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/app/worker.php b/app/worker.php index 06dc4c44d8..fd9681b37e 100644 --- a/app/worker.php +++ b/app/worker.php @@ -380,20 +380,6 @@ try { $worker = $platform->getWorker(); -$worker - ->init() - ->inject('project') - ->inject('dbForConsole') - ->action(function (Document $project, Database $dbForConsole) { - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); - } - } - }); - $worker ->shutdown() ->inject('pools') From 0cdb2a98be906e86e6248ef78394c32ae9dcf48a Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 14:05:37 +0000 Subject: [PATCH 146/340] fix db name --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 2c43116c10..bb60b01ddd 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -96,7 +96,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $accessedAt = $project->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } From 2fb9ebe71df40a258f6c89d8d16a0ba8fc99f331 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 14:05:49 +0000 Subject: [PATCH 147/340] update project accessed at in schedules --- .../Platform/Tasks/ScheduleExecutions.php | 12 ++++++++++++ src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 15 +++++++++++++-- src/Appwrite/Platform/Tasks/ScheduleMessages.php | 14 +++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 50beb48e9d..9be7950fd6 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -5,6 +5,8 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Func; use Swoole\Coroutine as Co; use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleExecutions extends ScheduleBase @@ -57,6 +59,16 @@ class ScheduleExecutions extends ScheduleBase $delay = $scheduledAt->getTimestamp() - (new \DateTime())->getTimestamp(); + $project = $schedule['project']; + + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + \go(function () use ($queueForFunctions, $schedule, $delay, $data) { Co::sleep($delay); diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 156ff1e31d..d1a9662967 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -7,6 +7,7 @@ use Cron\CronExpression; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleFunctions extends ScheduleBase @@ -70,7 +71,7 @@ class ScheduleFunctions extends ScheduleBase } foreach ($delayedExecutions as $delay => $scheduleKeys) { - \go(function () use ($delay, $scheduleKeys, $pools) { + \go(function () use ($delay, $scheduleKeys, $pools, $dbForPlatform) { \sleep($delay); // in seconds $queue = $pools->get('queue')->pop(); @@ -84,6 +85,16 @@ class ScheduleFunctions extends ScheduleBase $schedule = $this->schedules[$scheduleKey]; + $project = $schedule['project']; + + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + $queueForFunctions = new Func($connection); $queueForFunctions @@ -91,7 +102,7 @@ class ScheduleFunctions extends ScheduleBase ->setFunction($schedule['resource']) ->setMethod('POST') ->setPath('/') - ->setProject($schedule['project']) + ->setProject($project) ->trigger(); } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 2136e62f08..3beb8c48fb 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -4,6 +4,8 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Messaging; use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleMessages extends ScheduleBase @@ -45,10 +47,20 @@ class ScheduleMessages extends ScheduleBase $connection = $queue->getResource(); $queueForMessaging = new Messaging($connection); + $project = $schedule['project']; + + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + $queueForMessaging ->setType(MESSAGE_SEND_TYPE_EXTERNAL) ->setMessageId($schedule['resourceId']) - ->setProject($schedule['project']) + ->setProject($project) ->trigger(); $dbForPlatform->deleteDocument( From d7d69b63a8f95eefc895a532079fbc56ea741045 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 14:15:27 +0000 Subject: [PATCH 148/340] reset worker --- app/worker.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/worker.php b/app/worker.php index fd9681b37e..563a801b6b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -62,13 +62,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $project; } - // NOT all workers need valid DB config so we return empty if this fails - try { - return $dbForPlatform->getDocument('projects', $project->getId()); - } catch (\Throwable $e) { - return new Document([]); - } - + return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { @@ -435,4 +429,4 @@ $worker->workerStart() Console::info("Worker $workerName started"); }); -$worker->start(); +$worker->start(); \ No newline at end of file From e24cce4e48aee24b6fc8e6713565e82bf1b340d1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani <dlohani48@gmail.com> Date: Tue, 17 Dec 2024 14:19:26 +0000 Subject: [PATCH 149/340] refactor --- app/worker.php | 2 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 12 ++++++++++++ src/Appwrite/Platform/Tasks/ScheduleExecutions.php | 12 +----------- src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 13 ++----------- src/Appwrite/Platform/Tasks/ScheduleMessages.php | 14 ++------------ 5 files changed, 18 insertions(+), 35 deletions(-) diff --git a/app/worker.php b/app/worker.php index 563a801b6b..2c7d8acb22 100644 --- a/app/worker.php +++ b/app/worker.php @@ -429,4 +429,4 @@ $worker->workerStart() Console::info("Worker $workerName started"); }); -$worker->start(); \ No newline at end of file +$worker->start(); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 10623e7fa5..dad2db0d9a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -9,6 +9,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\System\System; @@ -39,6 +40,17 @@ abstract class ScheduleBase extends Action ->callback(fn (Group $pools, Database $dbForPlatform, callable $getProjectDB) => $this->action($pools, $dbForPlatform, $getProjectDB)); } + protected function updateProjectAccess(Document $project, Database $dbForPlatform): void + { + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + } + /** * 1. Load all documents from 'schedules' collection to create local copy * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 9be7950fd6..086bad513e 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -5,8 +5,6 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Func; use Swoole\Coroutine as Co; use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleExecutions extends ScheduleBase @@ -59,15 +57,7 @@ class ScheduleExecutions extends ScheduleBase $delay = $scheduledAt->getTimestamp() - (new \DateTime())->getTimestamp(); - $project = $schedule['project']; - - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); - } - } + $this->updateProjectAccess($schedule['project'], $dbForPlatform); \go(function () use ($queueForFunctions, $schedule, $delay, $data) { Co::sleep($delay); diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index d1a9662967..c443bb6c2d 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -7,7 +7,6 @@ use Cron\CronExpression; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleFunctions extends ScheduleBase @@ -85,15 +84,7 @@ class ScheduleFunctions extends ScheduleBase $schedule = $this->schedules[$scheduleKey]; - $project = $schedule['project']; - - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); - } - } + $this->updateProjectAccess($schedule['project'], $dbForPlatform); $queueForFunctions = new Func($connection); @@ -102,7 +93,7 @@ class ScheduleFunctions extends ScheduleBase ->setFunction($schedule['resource']) ->setMethod('POST') ->setPath('/') - ->setProject($project) + ->setProject($schedule['project']) ->trigger(); } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 3beb8c48fb..5d997fc5bb 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -4,8 +4,6 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Messaging; use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Validator\Authorization; use Utopia\Pools\Group; class ScheduleMessages extends ScheduleBase @@ -47,20 +45,12 @@ class ScheduleMessages extends ScheduleBase $connection = $queue->getResource(); $queueForMessaging = new Messaging($connection); - $project = $schedule['project']; - - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); - } - } + $this->updateProjectAccess($schedule['project'], $dbForPlatform); $queueForMessaging ->setType(MESSAGE_SEND_TYPE_EXTERNAL) ->setMessageId($schedule['resourceId']) - ->setProject($project) + ->setProject($schedule['project']) ->trigger(); $dbForPlatform->deleteDocument( From 01393faf0bce3a2bca29f72b9596e4d9d448148d Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 11:58:34 +0530 Subject: [PATCH 150/340] feat: update abuse library --- app/controllers/api/functions.php | 9 +++--- app/controllers/shared/api.php | 8 ++--- app/init.php | 8 +++++ app/realtime.php | 13 ++++++-- composer.json | 2 +- composer.lock | 39 ++++++++++++++--------- src/Appwrite/Platform/Workers/Deletes.php | 16 +++++----- 7 files changed, 60 insertions(+), 35 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 5934258037..b997d79733 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -24,7 +24,7 @@ use Appwrite\Utopia\Response\Model\Rule; use Executor\Executor; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -180,22 +180,23 @@ App::post('/v1/functions') ->inject('request') ->inject('response') ->inject('dbForProject') + ->inject('adapterForAbuse') ->inject('project') ->inject('user') ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, TimeLimit $adapterForAbuse, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check - $abuseCheck = function () use ($project, $dbForProject, $response) { + $abuseCheck = function () use ($project, $adapterForAbuse, $response) { $abuseKey = "projectId:{projectId},url:{url}"; $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); $abuseTime = 86400; // 1 day - $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); + $timeLimit = $adapterForAbuse($abuseKey, $abuseLimit, $abuseTime); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{url}', '/v1/functions'); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 9a15467ec0..59e5012fe9 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -19,7 +19,7 @@ use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Redis\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -420,9 +420,9 @@ App::init() ->inject('queueForBuilds') ->inject('queueForUsage') ->inject('dbForProject') - ->inject('redis') + ->inject('adapterForAbuse') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, \Redis $redis, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, TimeLimit $adapterForAbuse, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -445,7 +445,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $redis); + $timeLimit = $adapterForAbuse($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) diff --git a/app/init.php b/app/init.php index 056e8ed3d5..0c6ff1f57b 100644 --- a/app/init.php +++ b/app/init.php @@ -48,6 +48,7 @@ use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use PHPMailer\PHPMailer\PHPMailer; use Swoole\Database\PDOProxy; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Adapter\Sharding; @@ -93,6 +94,7 @@ use Utopia\Validator\Range; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub; +use Redis; const APP_NAME = 'Appwrite'; const APP_DOMAIN = 'appwrite.io'; @@ -1546,6 +1548,12 @@ App::setResource('redis', function () { return $redis; }); +App::setResource('adapterForAbuse', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $redis); + }; +}, ['redis']); + App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/app/realtime.php b/app/realtime.php index 2df8abfbfa..59212e14f1 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Redis\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -157,6 +157,13 @@ if (!function_exists('getRedis')) { } } +if (!function_exists('getAdapterForAbuse')) { + function getAdapterForAbuse(): TimeLimit + { + return new TimeLimit("", 0, 1, getRedis()); + } +} + if (!function_exists('getRealtime')) { function getRealtime(): Realtime { @@ -500,7 +507,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $redis = $app->getResource('redis'); + $adapterForAbuse = $app->getResource('adapterForAbuse'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -509,7 +516,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $redis); + $timeLimit = $adapterForAbuse('url:{url},ip:{ip}', 128, 60); $timeLimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); diff --git a/composer.json b/composer.json index 512e203a5e..c4d4bfeb75 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.43.*", + "utopia-php/abuse": "dev-add-support-for-sharding-adapter as 0.43.1000", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 37a5c81436..14135bc27f 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": "fae350df93342992edd8f639948e1570", + "content-hash": "2dd50e9cf2c2b74a56ea42d8593ffc0a", "packages": [ { "name": "adhocore/jwt", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.2", + "version": "dev-add-support-for-sharding-adapter", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "374536b86d8d39066960a7da161d444a099bbc56" + "reference": "627d1ba56451dd70ca26a1253c42e039b4bfc1a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", - "reference": "374536b86d8d39066960a7da161d444a099bbc56", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/627d1ba56451dd70ca26a1253c42e039b4bfc1a7", + "reference": "627d1ba56451dd70ca26a1253c42e039b4bfc1a7", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.2" + "source": "https://github.com/utopia-php/abuse/tree/add-support-for-sharding-adapter" }, - "time": "2024-12-12T19:43:24+00:00" + "time": "2024-12-18T06:08:34+00:00" }, { "name": "utopia-php/analytics", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.26", + "version": "0.39.27", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c" + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/39768deacb4913f93548c46fa0149c3fadc62d0c", - "reference": "39768deacb4913f93548c46fa0149c3fadc62d0c", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/27d8ecde30e40cbfe1124cc0430c406d3e144849", + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849", "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.26" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.27" }, - "time": "2024-12-12T10:51:34+00:00" + "time": "2024-12-16T11:32:02+00:00" }, { "name": "doctrine/annotations", @@ -8554,9 +8554,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/abuse", + "version": "dev-add-support-for-sharding-adapter", + "alias": "0.43.1000", + "alias_normalized": "0.43.1000.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/abuse": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 6fa65ec842..d6bba4b88a 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -8,7 +8,7 @@ use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Redis\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -47,7 +47,7 @@ class Deletes extends Action ->inject('message') ->inject('dbForPlatform') ->inject('getProjectDB') - ->inject('redis') + ->inject('adapterForAbuse') ->inject('deviceForFiles') ->inject('deviceForFunctions') ->inject('deviceForBuilds') @@ -58,8 +58,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $redis, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, TimeLimit $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $adapterForAbuse, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -67,7 +67,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, \Redis $redis, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, TimeLimit $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -127,7 +127,7 @@ class Deletes extends Action } break; case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $redis, $abuseRetention); + $this->deleteAbuseLogs($project, $adapterForAbuse, $abuseRetention); break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForPlatform, $datetime); @@ -708,10 +708,10 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, \Redis $redis, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, TimeLimit $adapterForAbuse, string $abuseRetention): void { $projectId = $project->getId(); - $timeLimit = new TimeLimit("", 0, 1, $redis); + $timeLimit = $adapterForAbuse("", 0, 1); $abuse = new Abuse($timeLimit); try { From f1a089f8c6386e78abb023de3ace4adb2dd16247 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 12:57:52 +0530 Subject: [PATCH 151/340] feat: fix tests --- app/controllers/api/functions.php | 2 +- app/controllers/shared/api.php | 2 +- src/Appwrite/Platform/Workers/Deletes.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index b997d79733..bdcb6b3286 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -187,7 +187,7 @@ App::post('/v1/functions') ->inject('queueForBuilds') ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, TimeLimit $adapterForAbuse, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, callable $adapterForAbuse, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 59e5012fe9..148c7282e7 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -422,7 +422,7 @@ App::init() ->inject('dbForProject') ->inject('adapterForAbuse') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, TimeLimit $adapterForAbuse, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, callable $adapterForAbuse, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index d6bba4b88a..dae5f9fe58 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -58,7 +58,7 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, TimeLimit $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + fn ($message, $dbForPlatform, callable $getProjectDB, callable $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => $this->action($message, $dbForPlatform, $getProjectDB, $adapterForAbuse, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -67,7 +67,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, TimeLimit $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -708,7 +708,7 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, TimeLimit $adapterForAbuse, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, callable $adapterForAbuse, string $abuseRetention): void { $projectId = $project->getId(); $timeLimit = $adapterForAbuse("", 0, 1); From 911edd9457d6d46560e7ca5e4367b10add5f995d Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 13:08:17 +0530 Subject: [PATCH 152/340] chore: linter --- app/controllers/api/functions.php | 1 - app/controllers/shared/api.php | 1 - app/init.php | 1 - composer.json | 2 +- composer.lock | 11 ++--------- src/Appwrite/Platform/Workers/Deletes.php | 1 - 6 files changed, 3 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index bdcb6b3286..219832077f 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -24,7 +24,6 @@ use Appwrite\Utopia\Response\Model\Rule; use Executor\Executor; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 148c7282e7..50a4a1e02e 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -19,7 +19,6 @@ use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; diff --git a/app/init.php b/app/init.php index 0c6ff1f57b..5282c7f70d 100644 --- a/app/init.php +++ b/app/init.php @@ -94,7 +94,6 @@ use Utopia\Validator\Range; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub; -use Redis; const APP_NAME = 'Appwrite'; const APP_DOMAIN = 'appwrite.io'; diff --git a/composer.json b/composer.json index c4d4bfeb75..5f81fd7752 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "dev-add-support-for-sharding-adapter as 0.43.1000", + "utopia-php/abuse": "dev-add-support-for-sharding-adapter", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 14135bc27f..81690cc718 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": "2dd50e9cf2c2b74a56ea42d8593ffc0a", + "content-hash": "d2345c93c578d7ac06f364fc5a175810", "packages": [ { "name": "adhocore/jwt", @@ -8554,14 +8554,7 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/abuse", - "version": "dev-add-support-for-sharding-adapter", - "alias": "0.43.1000", - "alias_normalized": "0.43.1000.0" - } - ], + "aliases": [], "minimum-stability": "stable", "stability-flags": { "utopia-php/abuse": 20 diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index dae5f9fe58..bd9a8f976b 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -8,7 +8,6 @@ use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; From 77a8c271531ff78f85c56dc7dc5d5c60c5cb3100 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 13:26:31 +0530 Subject: [PATCH 153/340] chore: fix realtime tests --- app/realtime.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index 59212e14f1..78b17a3a78 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -619,8 +619,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $redis = getRedis(); - $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $redis); + $timeLimit = getAdapterForAbuse('url:{url},connection:{connection}', 32, 60); $timeLimit ->setParam('{connection}', $connection) From 599cc5e19afffe8bef10c4c720883a7ecb32b3dd Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 15:57:04 +0530 Subject: [PATCH 154/340] chore: review comments --- app/controllers/api/functions.php | 8 ++++---- app/controllers/shared/api.php | 6 +++--- app/init.php | 2 +- app/realtime.php | 14 +++++++------- src/Appwrite/Platform/Workers/Deletes.php | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 219832077f..86fea8a60d 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -179,23 +179,23 @@ App::post('/v1/functions') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('adapterForAbuse') + ->inject('timelimit') ->inject('project') ->inject('user') ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, callable $adapterForAbuse, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, callable $timelimit, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check - $abuseCheck = function () use ($project, $adapterForAbuse, $response) { + $abuseCheck = function () use ($project, $timelimit, $response) { $abuseKey = "projectId:{projectId},url:{url}"; $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); $abuseTime = 86400; // 1 day - $timeLimit = $adapterForAbuse($abuseKey, $abuseLimit, $abuseTime); + $timeLimit = $timelimit($abuseKey, $abuseLimit, $abuseTime); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{url}', '/v1/functions'); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 50a4a1e02e..7752f2f8a9 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -419,9 +419,9 @@ App::init() ->inject('queueForBuilds') ->inject('queueForUsage') ->inject('dbForProject') - ->inject('adapterForAbuse') + ->inject('timelimit') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, callable $adapterForAbuse, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, callable $timelimit, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -444,7 +444,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = $adapterForAbuse($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); + $timeLimit = $timelimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) diff --git a/app/init.php b/app/init.php index 5282c7f70d..a738a44577 100644 --- a/app/init.php +++ b/app/init.php @@ -1547,7 +1547,7 @@ App::setResource('redis', function () { return $redis; }); -App::setResource('adapterForAbuse', function (\Redis $redis) { +App::setResource('timelimit', function (\Redis $redis) { return function (string $key, int $limit, int $time) use ($redis) { return new TimeLimitRedis($key, $limit, $time, $redis); }; diff --git a/app/realtime.php b/app/realtime.php index 78b17a3a78..d47098340e 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -157,8 +157,8 @@ if (!function_exists('getRedis')) { } } -if (!function_exists('getAdapterForAbuse')) { - function getAdapterForAbuse(): TimeLimit +if (!function_exists('getTimelimit')) { + function getTimelimit(): TimeLimit { return new TimeLimit("", 0, 1, getRedis()); } @@ -507,7 +507,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $adapterForAbuse = $app->getResource('adapterForAbuse'); + $timelimit = $app->getResource('timelimit'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -516,12 +516,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = $adapterForAbuse('url:{url},ip:{ip}', 128, 60); - $timeLimit + $timelimit = $timelimit('url:{url},ip:{ip}', 128, 60); + $timelimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); - $abuse = new Abuse($timeLimit); + $abuse = new Abuse($timelimit); if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) { throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests'); @@ -619,7 +619,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = getAdapterForAbuse('url:{url},connection:{connection}', 32, 60); + $timeLimit = getTimelimit('url:{url},connection:{connection}', 32, 60); $timeLimit ->setParam('{connection}', $connection) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index bd9a8f976b..bbc808e248 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -46,7 +46,7 @@ class Deletes extends Action ->inject('message') ->inject('dbForPlatform') ->inject('getProjectDB') - ->inject('adapterForAbuse') + ->inject('timelimit') ->inject('deviceForFiles') ->inject('deviceForFunctions') ->inject('deviceForBuilds') @@ -57,8 +57,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, callable $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $adapterForAbuse, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $adapterForAbuse, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -126,7 +126,7 @@ class Deletes extends Action } break; case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $adapterForAbuse, $abuseRetention); + $this->deleteAbuseLogs($project, $timelimit, $abuseRetention); break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForPlatform, $datetime); @@ -707,10 +707,10 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, callable $adapterForAbuse, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, callable $timelimit, string $abuseRetention): void { $projectId = $project->getId(); - $timeLimit = $adapterForAbuse("", 0, 1); + $timeLimit = $timelimit("", 0, 1); $abuse = new Abuse($timeLimit); try { From d0f04126f3d4795abf8b8a6f9f7d978a557c2339 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 19:59:49 +0530 Subject: [PATCH 155/340] chore: add missing resources to workers --- app/worker.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/app/worker.php b/app/worker.php index 2c7d8acb22..7539a26879 100644 --- a/app/worker.php +++ b/app/worker.php @@ -17,6 +17,7 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -200,6 +201,27 @@ Server::setResource('cache', function (Registry $register) { return new Cache(new Sharding($adapters)); }, ['register']); +Server::setResource('redis', function () { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; +}); + +Server::setResource('timelimit', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $redis); + }; +}, ['redis']); + Server::setResource('log', fn () => new Log()); Server::setResource('queueForUsage', function (Connection $queue) { From 5a9dbe9c80b7d1fa121ee0be1ea724af1193a525 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 20:06:24 +0530 Subject: [PATCH 156/340] chore: fix realtime test --- app/realtime.php | 6 +++--- phpunit.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index d47098340e..4f87e4dea1 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -158,9 +158,9 @@ if (!function_exists('getRedis')) { } if (!function_exists('getTimelimit')) { - function getTimelimit(): TimeLimit + function getTimelimit(): TimeLimitRedis { - return new TimeLimit("", 0, 1, getRedis()); + return new TimeLimitRedis("", 0, 1, getRedis()); } } diff --git a/phpunit.xml b/phpunit.xml index 4c4e55ea4e..598b730908 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > <extensions> <extension class="Appwrite\Tests\TestHook" /> From 12cb3b10bd6283fb00dc0b46b590bf2f228b145f Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 18 Dec 2024 20:42:29 +0530 Subject: [PATCH 157/340] chore: update abuse library --- composer.json | 2 +- composer.lock | 30 ++++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 5f81fd7752..a8a54c75ab 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "dev-add-support-for-sharding-adapter", + "utopia-php/abuse": "0.44.*", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 81690cc718..09f9b3aed9 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": "d2345c93c578d7ac06f364fc5a175810", + "content-hash": "fd1cf738be4e037abdc1a0fa4cb27a3c", "packages": [ { "name": "adhocore/jwt", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.29.1", + "version": "v4.29.2", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "6042b5483f8029e42473faeb8ef75ba266278381" + "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/6042b5483f8029e42473faeb8ef75ba266278381", - "reference": "6042b5483f8029e42473faeb8ef75ba266278381", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/79aa5014efeeec3d137df5cdb0ae2fc163953945", + "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.1" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.2" }, - "time": "2024-12-03T22:07:45+00:00" + "time": "2024-12-18T14:11:12+00:00" }, { "name": "jean85/pretty-package-versions", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "dev-add-support-for-sharding-adapter", + "version": "0.44.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "627d1ba56451dd70ca26a1253c42e039b4bfc1a7" + "reference": "25b9654ddfb1a17161debf1d26f2915e0128d9fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/627d1ba56451dd70ca26a1253c42e039b4bfc1a7", - "reference": "627d1ba56451dd70ca26a1253c42e039b4bfc1a7", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/25b9654ddfb1a17161debf1d26f2915e0128d9fd", + "reference": "25b9654ddfb1a17161debf1d26f2915e0128d9fd", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/add-support-for-sharding-adapter" + "source": "https://github.com/utopia-php/abuse/tree/0.44.0" }, - "time": "2024-12-18T06:08:34+00:00" + "time": "2024-12-18T15:09:47+00:00" }, { "name": "utopia-php/analytics", @@ -8556,9 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/abuse": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 53d8e2b0c3e07598a5d2c22f30f71ed16abed1bb Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 16:43:05 +0530 Subject: [PATCH 158/340] chore: optimise webhooks payload --- src/Appwrite/Event/Webhook.php | 12 ++++++++++++ src/Appwrite/Platform/Workers/Webhooks.php | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 125c9a78d5..6457c53e68 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -14,4 +14,16 @@ class Webhook extends Event ->setQueue(Event::WEBHOOK_QUEUE_NAME) ->setClass(Event::WEBHOOK_CLASS_NAME); } + + public function trigger(): string|bool + { + /** Filter out context and trim project to keep the payload small */ + $this->context = []; + $this->project = [ + '$id' => $this->project->getId(), + '$internalId' => $this->project->getAttribute('internalId'), + ]; + + return parent::trigger(); + } } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index ba0bdaa6a3..271c4c00f0 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -56,9 +56,10 @@ class Webhooks extends Action $events = $payload['events']; $webhookPayload = json_encode($payload['payload']); - $project = new Document($payload['project']); $user = new Document($payload['user'] ?? []); + $project = new Document($payload['project']); + $project = $dbForPlatform->getDocument('projects', $project->getId()); $log->addTag('projectId', $project->getId()); foreach ($project->getAttribute('webhooks', []) as $webhook) { From d03d3c05b4d1c9331029981e345912d81504875e Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 16:52:10 +0530 Subject: [PATCH 159/340] chore: optimise webhooks payload --- src/Appwrite/Event/Webhook.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 6457c53e68..e4c4f5e210 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -3,6 +3,7 @@ namespace Appwrite\Event; use Utopia\Queue\Connection; +use Utopia\Database\Document; class Webhook extends Event { @@ -19,10 +20,10 @@ class Webhook extends Event { /** Filter out context and trim project to keep the payload small */ $this->context = []; - $this->project = [ + $this->project = new Document([ '$id' => $this->project->getId(), '$internalId' => $this->project->getAttribute('internalId'), - ]; + ]); return parent::trigger(); } From 6ec640cfd5905e42455f0468eec477a1c53d50ec Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 16:56:17 +0530 Subject: [PATCH 160/340] chore: linter --- src/Appwrite/Event/Webhook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index e4c4f5e210..954e8df1fd 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -2,8 +2,8 @@ namespace Appwrite\Event; -use Utopia\Queue\Connection; use Utopia\Database\Document; +use Utopia\Queue\Connection; class Webhook extends Event { From b97dea7996f7fd217562cff675d7fb996605fe90 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 20:27:54 +0530 Subject: [PATCH 161/340] Revert "chore: initial commit" --- app/controllers/api/functions.php | 8 +- app/controllers/api/projects.php | 15 ++++ app/controllers/shared/api.php | 6 +- app/http.php | 7 ++ app/init.php | 36 ++------ app/realtime.php | 38 ++------ app/worker.php | 22 ----- composer.json | 2 +- composer.lock | 102 +++++++++++----------- phpunit.xml | 2 +- src/Appwrite/Platform/Workers/Deletes.php | 18 ++-- 11 files changed, 105 insertions(+), 151 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 86fea8a60d..5934258037 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -24,6 +24,7 @@ use Appwrite\Utopia\Response\Model\Rule; use Executor\Executor; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -179,23 +180,22 @@ App::post('/v1/functions') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('timelimit') ->inject('project') ->inject('user') ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, callable $timelimit, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check - $abuseCheck = function () use ($project, $timelimit, $response) { + $abuseCheck = function () use ($project, $dbForProject, $response) { $abuseKey = "projectId:{projectId},url:{url}"; $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); $abuseTime = 86400; // 1 day - $timeLimit = $timelimit($abuseKey, $abuseLimit, $abuseTime); + $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{url}', '/v1/functions'); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index cbda6ad544..388c9e22ea 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -16,6 +16,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; @@ -228,6 +229,9 @@ App::post('/v1/projects') if ($create || $projectTables) { $audit = new Audit($dbForProject); $audit->setup(); + + $abuse = new TimeLimit('', 0, 1, $dbForProject); + $abuse->setup(); } if (!$create && $sharedTablesV1) { @@ -241,6 +245,17 @@ App::post('/v1/projects') 'indexes' => $indexes, 'documentSecurity' => true ])); + + $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('abuse'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'abuse', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); } if ($create || $sharedTablesV1) { diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 7752f2f8a9..a0f65eb484 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -19,6 +19,7 @@ use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -419,9 +420,8 @@ App::init() ->inject('queueForBuilds') ->inject('queueForUsage') ->inject('dbForProject') - ->inject('timelimit') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, callable $timelimit, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -444,7 +444,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = $timelimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); + $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) diff --git a/app/http.php b/app/http.php index 61afce3eae..74b829c384 100644 --- a/app/http.php +++ b/app/http.php @@ -10,8 +10,10 @@ use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; use Swoole\Process; use Swoole\Table; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; +use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; @@ -198,6 +200,11 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $audit->setup(); } + if ($dbForPlatform->getCollection(TimeLimit::COLLECTION)->isEmpty()) { + $adapter = new TimeLimit("", 0, 1, $dbForPlatform); + $adapter->setup(); + } + /** @var array $collections */ $collections = Config::getParam('collections', []); $consoleCollections = $collections['console']; diff --git a/app/init.php b/app/init.php index a738a44577..109849fdce 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,6 @@ use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use PHPMailer\PHPMailer\PHPMailer; use Swoole\Database\PDOProxy; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Adapter\Sharding; @@ -854,31 +853,31 @@ $register->set('pools', function () { $connections = [ 'console' => [ 'type' => 'database', - 'dsns' => $fallbackForDB, + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), 'multiple' => false, 'schemes' => ['mariadb', 'mysql'], ], 'database' => [ 'type' => 'database', - 'dsns' => $fallbackForDB, + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), 'multiple' => true, 'schemes' => ['mariadb', 'mysql'], ], 'queue' => [ 'type' => 'queue', - 'dsns' => $fallbackForRedis, + 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), 'multiple' => false, 'schemes' => ['redis'], ], 'pubsub' => [ 'type' => 'pubsub', - 'dsns' => $fallbackForRedis, + 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), 'multiple' => false, 'schemes' => ['redis'], ], 'cache' => [ 'type' => 'cache', - 'dsns' => $fallbackForRedis, + 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), 'multiple' => true, 'schemes' => ['redis'], ], @@ -950,12 +949,12 @@ $register->set('pools', function () { }); }, 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new \Redis(); + $redis = new Redis(); @$redis->pconnect($dsnHost, (int)$dsnPort); if ($dsnPass) { $redis->auth($dsnPass); } - $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); return $redis; }, @@ -1532,27 +1531,6 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); -App::setResource('redis', function () { - $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); - $port = System::getEnv('_APP_REDIS_PORT', 6379); - $pass = System::getEnv('_APP_REDIS_PASS', ''); - - $redis = new \Redis(); - @$redis->pconnect($host, (int)$port); - if ($pass) { - $redis->auth($pass); - } - $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); - - return $redis; -}); - -App::setResource('timelimit', function (\Redis $redis) { - return function (string $key, int $limit, int $time) use ($redis) { - return new TimeLimitRedis($key, $limit, $time, $redis); - }; -}, ['redis']); - App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/app/realtime.php b/app/realtime.php index 4f87e4dea1..54fd1e05f7 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -138,32 +138,6 @@ if (!function_exists('getCache')) { } } -// Allows overriding -if (!function_exists('getRedis')) { - function getRedis(): \Redis - { - $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); - $port = System::getEnv('_APP_REDIS_PORT', 6379); - $pass = System::getEnv('_APP_REDIS_PASS', ''); - - $redis = new \Redis(); - @$redis->pconnect($host, (int)$port); - if ($pass) { - $redis->auth($pass); - } - $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); - - return $redis; - } -} - -if (!function_exists('getTimelimit')) { - function getTimelimit(): TimeLimitRedis - { - return new TimeLimitRedis("", 0, 1, getRedis()); - } -} - if (!function_exists('getRealtime')) { function getRealtime(): Realtime { @@ -507,7 +481,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $timelimit = $app->getResource('timelimit'); + $dbForProject = getProjectDB($project); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -516,12 +490,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timelimit = $timelimit('url:{url},ip:{ip}', 128, 60); - $timelimit + $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject); + $timeLimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); - $abuse = new Abuse($timelimit); + $abuse = new Abuse($timeLimit); if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) { throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests'); @@ -619,7 +593,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = getTimelimit('url:{url},connection:{connection}', 32, 60); + $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database); $timeLimit ->setParam('{connection}', $connection) diff --git a/app/worker.php b/app/worker.php index 7539a26879..2c7d8acb22 100644 --- a/app/worker.php +++ b/app/worker.php @@ -17,7 +17,6 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -201,27 +200,6 @@ Server::setResource('cache', function (Registry $register) { return new Cache(new Sharding($adapters)); }, ['register']); -Server::setResource('redis', function () { - $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); - $port = System::getEnv('_APP_REDIS_PORT', 6379); - $pass = System::getEnv('_APP_REDIS_PASS', ''); - - $redis = new \Redis(); - @$redis->pconnect($host, (int)$port); - if ($pass) { - $redis->auth($pass); - } - $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); - - return $redis; -}); - -Server::setResource('timelimit', function (\Redis $redis) { - return function (string $key, int $limit, int $time) use ($redis) { - return new TimeLimitRedis($key, $limit, $time, $redis); - }; -}, ['redis']); - Server::setResource('log', fn () => new Log()); Server::setResource('queueForUsage', function (Connection $queue) { diff --git a/composer.json b/composer.json index a8a54c75ab..512e203a5e 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.44.*", + "utopia-php/abuse": "0.43.*", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 09f9b3aed9..732bafd219 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": "fd1cf738be4e037abdc1a0fa4cb27a3c", + "content-hash": "fae350df93342992edd8f639948e1570", "packages": [ { "name": "adhocore/jwt", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.29.2", + "version": "v4.29.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945" + "reference": "6042b5483f8029e42473faeb8ef75ba266278381" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/79aa5014efeeec3d137df5cdb0ae2fc163953945", - "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/6042b5483f8029e42473faeb8ef75ba266278381", + "reference": "6042b5483f8029e42473faeb8ef75ba266278381", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.2" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.1" }, - "time": "2024-12-18T14:11:12+00:00" + "time": "2024-12-03T22:07:45+00:00" }, { "name": "jean85/pretty-package-versions", @@ -1237,16 +1237,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.2", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", - "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", + "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", "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-11-16T04:32:30+00:00" + "time": "2024-10-15T22:42:37+00:00" }, { "name": "open-telemetry/context", @@ -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": { @@ -2453,23 +2453,23 @@ }, { "name": "symfony/http-client", - "version": "v7.2.1", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "url": "https://api.github.com/repos/symfony/http-client/zipball/955e43336aff03df1e8a8e17daefabb0127a313b", + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.1" + "source": "https://github.com/symfony/http-client/tree/v7.2.0" }, "funding": [ { @@ -2544,20 +2544,20 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2024-11-29T08:22:02+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", "shasum": "" }, "require": { @@ -2606,7 +2606,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" }, "funding": [ { @@ -2622,7 +2622,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2024-11-25T12:02:18+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2650,8 +2650,8 @@ "type": "library", "extra": { "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.44.0", + "version": "0.43.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "25b9654ddfb1a17161debf1d26f2915e0128d9fd" + "reference": "374536b86d8d39066960a7da161d444a099bbc56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/25b9654ddfb1a17161debf1d26f2915e0128d9fd", - "reference": "25b9654ddfb1a17161debf1d26f2915e0128d9fd", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", + "reference": "374536b86d8d39066960a7da161d444a099bbc56", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.44.0" + "source": "https://github.com/utopia-php/abuse/tree/0.43.2" }, - "time": "2024-12-18T15:09:47+00:00" + "time": "2024-12-12T19:43:24+00:00" }, { "name": "utopia-php/analytics", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.27", + "version": "0.39.25", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849" + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/27d8ecde30e40cbfe1124cc0430c406d3e144849", - "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5b5323636a8d75a1c4faaae9728098dd6a6a47d1", + "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1", "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.27" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.25" }, - "time": "2024-12-16T11:32:02+00:00" + "time": "2024-11-08T10:16:34+00:00" }, { "name": "doctrine/annotations", @@ -7576,16 +7576,16 @@ }, { "name": "symfony/console", - "version": "v7.2.1", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "url": "https://api.github.com/repos/symfony/console/zipball/23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", + "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", "shasum": "" }, "require": { @@ -7649,7 +7649,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.1" + "source": "https://github.com/symfony/console/tree/v7.2.0" }, "funding": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-12-11T03:49:26+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/filesystem", diff --git a/phpunit.xml b/phpunit.xml index 598b730908..4c4e55ea4e 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > <extensions> <extension class="Appwrite\Tests\TestHook" /> diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index bbc808e248..f286ed4c4c 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -8,6 +8,7 @@ use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; use Utopia\Abuse\Abuse; +use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -46,7 +47,6 @@ class Deletes extends Action ->inject('message') ->inject('dbForPlatform') ->inject('getProjectDB') - ->inject('timelimit') ->inject('deviceForFiles') ->inject('deviceForFunctions') ->inject('deviceForBuilds') @@ -57,8 +57,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -126,7 +126,7 @@ class Deletes extends Action } break; case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $timelimit, $abuseRetention); + $this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention); break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForPlatform, $datetime); @@ -494,7 +494,8 @@ class Deletes extends Action $projectCollectionIds = [ ...\array_keys(Config::getParam('collections', [])['projects']), - Audit::COLLECTION + Audit::COLLECTION, + TimeLimit::COLLECTION, ]; $limit = \count($projectCollectionIds) + 25; @@ -707,10 +708,11 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, callable $timelimit, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void { $projectId = $project->getId(); - $timeLimit = $timelimit("", 0, 1); + $dbForProject = $getProjectDB($project); + $timeLimit = new TimeLimit("", 0, 1, $dbForProject); $abuse = new Abuse($timeLimit); try { From 718edd37f7cec2190f440491474250337478a4e4 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 21:15:13 +0530 Subject: [PATCH 162/340] chore: fix attribute name --- src/Appwrite/Event/Webhook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 954e8df1fd..3b88fd4c54 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -22,7 +22,7 @@ class Webhook extends Event $this->context = []; $this->project = new Document([ '$id' => $this->project->getId(), - '$internalId' => $this->project->getAttribute('internalId'), + '$internalId' => $this->project->getAttribute('$internalId'), ]); return parent::trigger(); From e2bdb46d4836964cb8c0bf94e5c2c59c1acff505 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 19 Dec 2024 21:17:27 +0530 Subject: [PATCH 163/340] chore: fix attribute name --- src/Appwrite/Event/Webhook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 3b88fd4c54..36c6923cae 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -22,7 +22,7 @@ class Webhook extends Event $this->context = []; $this->project = new Document([ '$id' => $this->project->getId(), - '$internalId' => $this->project->getAttribute('$internalId'), + '$internalId' => $this->project->getInternalId(), ]); return parent::trigger(); From 50601bd454d177e1c9ff714f78f7ddd2928fbdcb Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 20 Dec 2024 20:14:50 +0530 Subject: [PATCH 164/340] chore: use redis adapter for abuse --- app/controllers/api/functions.php | 10 +- app/controllers/api/projects.php | 15 --- app/controllers/shared/api.php | 8 +- app/http.php | 7 -- app/init.php | 36 ++++++-- app/realtime.php | 38 ++++++-- app/worker.php | 22 +++++ composer.json | 2 +- composer.lock | 106 +++++++++++----------- src/Appwrite/Platform/Workers/Deletes.php | 18 ++-- 10 files changed, 155 insertions(+), 107 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 5934258037..d4d5fc64cf 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -24,7 +24,6 @@ use Appwrite\Utopia\Response\Model\Rule; use Executor\Executor; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -180,22 +179,23 @@ App::post('/v1/functions') ->inject('request') ->inject('response') ->inject('dbForProject') + ->inject('timelimit') ->inject('project') ->inject('user') ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('dbForPlatform') ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { + ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, callable $timelimit, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) { $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; // Temporary abuse check - $abuseCheck = function () use ($project, $dbForProject, $response) { + $abuseCheck = function () use ($project, $timelimit, $response) { $abuseKey = "projectId:{projectId},url:{url}"; $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); $abuseTime = 86400; // 1 day - $timeLimit = new TimeLimit($abuseKey, $abuseLimit, $abuseTime, $dbForProject); + $timeLimit = $timelimit($abuseKey, $abuseLimit, $abuseTime); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{url}', '/v1/functions'); @@ -203,7 +203,7 @@ App::post('/v1/functions') $abuse = new Abuse($timeLimit); $remaining = $timeLimit->remaining(); $limit = $timeLimit->limit(); - $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $abuseTime; + $time = $timeLimit->time() + $abuseTime; $response ->addHeader('X-RateLimit-Limit', $limit) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 388c9e22ea..cbda6ad544 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -16,7 +16,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; @@ -229,9 +228,6 @@ App::post('/v1/projects') if ($create || $projectTables) { $audit = new Audit($dbForProject); $audit->setup(); - - $abuse = new TimeLimit('', 0, 1, $dbForProject); - $abuse->setup(); } if (!$create && $sharedTablesV1) { @@ -245,17 +241,6 @@ App::post('/v1/projects') 'indexes' => $indexes, 'documentSecurity' => true ])); - - $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES); - $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES); - $dbForProject->createDocument(Database::METADATA, new Document([ - '$id' => ID::custom('abuse'), - '$permissions' => [Permission::create(Role::any())], - 'name' => 'abuse', - 'attributes' => $attributes, - 'indexes' => $indexes, - 'documentSecurity' => true - ])); } if ($create || $sharedTablesV1) { diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index a0f65eb484..012dd13c73 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -19,7 +19,6 @@ use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -420,8 +419,9 @@ App::init() ->inject('queueForBuilds') ->inject('queueForUsage') ->inject('dbForProject') + ->inject('timelimit') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, callable $timelimit, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -444,7 +444,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); + $timeLimit = $timelimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) @@ -472,7 +472,7 @@ App::init() $abuse = new Abuse($timeLimit); $remaining = $timeLimit->remaining(); $limit = $timeLimit->limit(); - $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $route->getLabel('abuse-time', 3600); + $time = $timeLimit->time() + $route->getLabel('abuse-time', 3600); if ($limit && ($remaining < $closestLimit || is_null($closestLimit))) { $closestLimit = $remaining; diff --git a/app/http.php b/app/http.php index 74b829c384..61afce3eae 100644 --- a/app/http.php +++ b/app/http.php @@ -10,10 +10,8 @@ use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; use Swoole\Process; use Swoole\Table; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; -use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; @@ -200,11 +198,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $audit->setup(); } - if ($dbForPlatform->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit("", 0, 1, $dbForPlatform); - $adapter->setup(); - } - /** @var array $collections */ $collections = Config::getParam('collections', []); $consoleCollections = $collections['console']; diff --git a/app/init.php b/app/init.php index 109849fdce..a738a44577 100644 --- a/app/init.php +++ b/app/init.php @@ -48,6 +48,7 @@ use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use PHPMailer\PHPMailer\PHPMailer; use Swoole\Database\PDOProxy; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Adapter\Sharding; @@ -853,31 +854,31 @@ $register->set('pools', function () { $connections = [ 'console' => [ 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), + 'dsns' => $fallbackForDB, 'multiple' => false, 'schemes' => ['mariadb', 'mysql'], ], 'database' => [ 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), + 'dsns' => $fallbackForDB, 'multiple' => true, 'schemes' => ['mariadb', 'mysql'], ], 'queue' => [ 'type' => 'queue', - 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => false, 'schemes' => ['redis'], ], 'pubsub' => [ 'type' => 'pubsub', - 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => false, 'schemes' => ['redis'], ], 'cache' => [ 'type' => 'cache', - 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), + 'dsns' => $fallbackForRedis, 'multiple' => true, 'schemes' => ['redis'], ], @@ -949,12 +950,12 @@ $register->set('pools', function () { }); }, 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new Redis(); + $redis = new \Redis(); @$redis->pconnect($dsnHost, (int)$dsnPort); if ($dsnPass) { $redis->auth($dsnPass); } - $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); return $redis; }, @@ -1531,6 +1532,27 @@ App::setResource('cache', function (Group $pools) { return new Cache(new Sharding($adapters)); }, ['pools']); +App::setResource('redis', function () { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; +}); + +App::setResource('timelimit', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $redis); + }; +}, ['redis']); + App::setResource('deviceForLocal', function () { return new Local(); }); diff --git a/app/realtime.php b/app/realtime.php index 54fd1e05f7..4f87e4dea1 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -138,6 +138,32 @@ if (!function_exists('getCache')) { } } +// Allows overriding +if (!function_exists('getRedis')) { + function getRedis(): \Redis + { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; + } +} + +if (!function_exists('getTimelimit')) { + function getTimelimit(): TimeLimitRedis + { + return new TimeLimitRedis("", 0, 1, getRedis()); + } +} + if (!function_exists('getRealtime')) { function getRealtime(): Realtime { @@ -481,7 +507,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $dbForProject = getProjectDB($project); + $timelimit = $app->getResource('timelimit'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -490,12 +516,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject); - $timeLimit + $timelimit = $timelimit('url:{url},ip:{ip}', 128, 60); + $timelimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); - $abuse = new Abuse($timeLimit); + $abuse = new Abuse($timelimit); if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) { throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests'); @@ -593,7 +619,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database); + $timeLimit = getTimelimit('url:{url},connection:{connection}', 32, 60); $timeLimit ->setParam('{connection}', $connection) diff --git a/app/worker.php b/app/worker.php index 2c7d8acb22..7539a26879 100644 --- a/app/worker.php +++ b/app/worker.php @@ -17,6 +17,7 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -200,6 +201,27 @@ Server::setResource('cache', function (Registry $register) { return new Cache(new Sharding($adapters)); }, ['register']); +Server::setResource('redis', function () { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; +}); + +Server::setResource('timelimit', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $redis); + }; +}, ['redis']); + Server::setResource('log', fn () => new Log()); Server::setResource('queueForUsage', function (Connection $queue) { diff --git a/composer.json b/composer.json index 512e203a5e..5f81fd7752 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.43.*", + "utopia-php/abuse": "dev-add-support-for-sharding-adapter", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 732bafd219..371a206a2c 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": "fae350df93342992edd8f639948e1570", + "content-hash": "d2345c93c578d7ac06f364fc5a175810", "packages": [ { "name": "adhocore/jwt", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.29.1", + "version": "v4.29.2", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "6042b5483f8029e42473faeb8ef75ba266278381" + "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/6042b5483f8029e42473faeb8ef75ba266278381", - "reference": "6042b5483f8029e42473faeb8ef75ba266278381", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/79aa5014efeeec3d137df5cdb0ae2fc163953945", + "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.1" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.2" }, - "time": "2024-12-03T22:07:45+00:00" + "time": "2024-12-18T14:11:12+00:00" }, { "name": "jean85/pretty-package-versions", @@ -1237,16 +1237,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" }, "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/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", "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": "2024-11-16T04:32:30+00:00" }, { "name": "open-telemetry/context", @@ -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": { @@ -2453,23 +2453,23 @@ }, { "name": "symfony/http-client", - "version": "v7.2.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" }, "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/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", "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.1" }, "funding": [ { @@ -2544,20 +2544,20 @@ "type": "tidelift" } ], - "time": "2024-11-29T08:22:02+00:00" + "time": "2024-12-07T08:50:44+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": { @@ -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": { @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.2", + "version": "dev-add-support-for-sharding-adapter", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "374536b86d8d39066960a7da161d444a099bbc56" + "reference": "d3119238ea05edd59f93ec99fb11545070e86eff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/374536b86d8d39066960a7da161d444a099bbc56", - "reference": "374536b86d8d39066960a7da161d444a099bbc56", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/d3119238ea05edd59f93ec99fb11545070e86eff", + "reference": "d3119238ea05edd59f93ec99fb11545070e86eff", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.2" + "source": "https://github.com/utopia-php/abuse/tree/add-support-for-sharding-adapter" }, - "time": "2024-12-12T19:43:24+00:00" + "time": "2024-12-20T14:11:20+00:00" }, { "name": "utopia-php/analytics", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.25", + "version": "0.39.27", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "5b5323636a8d75a1c4faaae9728098dd6a6a47d1" + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849" }, "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/27d8ecde30e40cbfe1124cc0430c406d3e144849", + "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849", "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.27" }, - "time": "2024-11-08T10:16:34+00:00" + "time": "2024-12-16T11:32:02+00:00" }, { "name": "doctrine/annotations", @@ -7576,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": { @@ -7649,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": [ { @@ -7665,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/filesystem", @@ -8556,7 +8556,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/abuse": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index f286ed4c4c..bbc808e248 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -8,7 +8,6 @@ use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -47,6 +46,7 @@ class Deletes extends Action ->inject('message') ->inject('dbForPlatform') ->inject('getProjectDB') + ->inject('timelimit') ->inject('deviceForFiles') ->inject('deviceForFunctions') ->inject('deviceForBuilds') @@ -57,8 +57,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -126,7 +126,7 @@ class Deletes extends Action } break; case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention); + $this->deleteAbuseLogs($project, $timelimit, $abuseRetention); break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForPlatform, $datetime); @@ -494,8 +494,7 @@ class Deletes extends Action $projectCollectionIds = [ ...\array_keys(Config::getParam('collections', [])['projects']), - Audit::COLLECTION, - TimeLimit::COLLECTION, + Audit::COLLECTION ]; $limit = \count($projectCollectionIds) + 25; @@ -708,11 +707,10 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, callable $timelimit, string $abuseRetention): void { $projectId = $project->getId(); - $dbForProject = $getProjectDB($project); - $timeLimit = new TimeLimit("", 0, 1, $dbForProject); + $timeLimit = $timelimit("", 0, 1); $abuse = new Abuse($timeLimit); try { From e9c8766a233d51ccdc6ba77751c9069deee65267 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 20 Dec 2024 21:53:12 +0530 Subject: [PATCH 165/340] chore: update abuse library --- composer.json | 2 +- composer.lock | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 5f81fd7752..2879993d3f 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "dev-add-support-for-sharding-adapter", + "utopia-php/abuse": "0.45.*", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 371a206a2c..5bce56a022 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": "d2345c93c578d7ac06f364fc5a175810", + "content-hash": "db3b63ba1be2561ee4a112e5b9c6bd53", "packages": [ { "name": "adhocore/jwt", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "dev-add-support-for-sharding-adapter", + "version": "0.45.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "d3119238ea05edd59f93ec99fb11545070e86eff" + "reference": "54a58355df1eb26c9be7834738debe6754e5581d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/d3119238ea05edd59f93ec99fb11545070e86eff", - "reference": "d3119238ea05edd59f93ec99fb11545070e86eff", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/54a58355df1eb26c9be7834738debe6754e5581d", + "reference": "54a58355df1eb26c9be7834738debe6754e5581d", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/add-support-for-sharding-adapter" + "source": "https://github.com/utopia-php/abuse/tree/0.45.0" }, - "time": "2024-12-20T14:11:20+00:00" + "time": "2024-12-20T16:18:52+00:00" }, { "name": "utopia-php/analytics", @@ -8556,9 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/abuse": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 25953732aba87a838f601ea62bcf44531928f710 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Mon, 23 Dec 2024 01:30:20 +0530 Subject: [PATCH 166/340] fix: deletes worker abuse retention type --- app/worker.php | 2 +- src/Appwrite/Platform/Workers/Deletes.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/worker.php b/app/worker.php index 7539a26879..6eb1363e9b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -174,7 +174,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf }, ['pools', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { - return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400)); + return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); }); Server::setResource('auditRetention', function () { diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index bbc808e248..5b6cfc1380 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -57,7 +57,7 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => + fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, int $executionRetention, int $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -703,11 +703,11 @@ class Deletes extends Action /** * @param Database $dbForPlatform * @param callable $getProjectDB - * @param string $datetime + * @param int $abuseRetention * @return void * @throws Exception */ - private function deleteAbuseLogs(Document $project, callable $timelimit, string $abuseRetention): void + private function deleteAbuseLogs(Document $project, callable $timelimit, int $abuseRetention): void { $projectId = $project->getId(); $timeLimit = $timelimit("", 0, 1); From cddace70a444fdb2396722960f5b678003c87244 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Mon, 23 Dec 2024 01:45:57 +0530 Subject: [PATCH 167/340] fix: deletes worker abuse retention type --- src/Appwrite/Platform/Workers/Deletes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 5b6cfc1380..f29b79e5db 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -66,7 +66,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, int $executionRetention, int $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; From fe19b0205ab94ef83d97fa1feb3ab49735910d12 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 23 Dec 2024 19:44:10 +0200 Subject: [PATCH 168/340] add webhooks usage stats --- app/init.php | 3 ++- src/Appwrite/Platform/Workers/Webhooks.php | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/init.php b/app/init.php index a738a44577..ff797e07c9 100644 --- a/app/init.php +++ b/app/init.php @@ -232,7 +232,8 @@ const API_KEY_DYNAMIC = 'dynamic'; // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; - +const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; +const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone'; const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}'; const METRIC_MESSAGES = 'messages'; diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 271c4c00f0..0ccfa036d8 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Workers; use Appwrite\Event\Mail; +use Appwrite\Event\Usage; use Appwrite\Template\Template; use Exception; use Utopia\Database\Database; @@ -33,8 +34,9 @@ class Webhooks extends Action ->inject('message') ->inject('dbForPlatform') ->inject('queueForMails') + ->inject('queueForUsage') ->inject('log') - ->callback(fn (Message $message, Database $dbForPlatform, Mail $queueForMails, Log $log) => $this->action($message, $dbForPlatform, $queueForMails, $log)); + ->callback(fn (Message $message, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log) => $this->action($message, $dbForPlatform, $queueForMails, $queueForUsage, $log)); } /** @@ -45,7 +47,7 @@ class Webhooks extends Action * @return void * @throws Exception */ - public function action(Message $message, Database $dbForPlatform, Mail $queueForMails, Log $log): void + public function action(Message $message, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log): void { $this->errors = []; $payload = $message->getPayload() ?? []; @@ -64,7 +66,7 @@ class Webhooks extends Action foreach ($project->getAttribute('webhooks', []) as $webhook) { if (array_intersect($webhook->getAttribute('events', []), $events)) { - $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails); + $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails, $queueForUsage); } } @@ -83,7 +85,7 @@ class Webhooks extends Action * @param Mail $queueForMails * @return void */ - private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails): void + private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage): void { if ($webhook->getAttribute('enabled') !== true) { return; @@ -166,11 +168,18 @@ class Webhooks extends Action $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $this->errors[] = $logs; + $queueForUsage->addMetric(METRIC_WEBHOOKS_FAILED, 1); + } else { $webhook->setAttribute('attempts', 0); // Reset attempts on success $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + $queueForUsage->addMetric(METRIC_WEBHOOKS_SENT, 1); } + + $queueForUsage + ->setProject($project) + ->trigger(); } /** From 4b033d8f00946e22d81862a7a05d1f4848060105 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Tue, 24 Dec 2024 10:50:09 +0200 Subject: [PATCH 169/340] add webhooks usage stats --- app/init.php | 4 ++++ src/Appwrite/Platform/Workers/Webhooks.php | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/init.php b/app/init.php index ff797e07c9..c6847610c2 100644 --- a/app/init.php +++ b/app/init.php @@ -234,6 +234,10 @@ const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; +const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; +const METRIC_WEBHOOK_ID_FAILED = '{webhookInternalId}.webhooks.events.failed'; + + const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone'; const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}'; const METRIC_MESSAGES = 'messages'; diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 0ccfa036d8..aa217dd6cf 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -168,13 +168,20 @@ class Webhooks extends Action $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $this->errors[] = $logs; - $queueForUsage->addMetric(METRIC_WEBHOOKS_FAILED, 1); + $queueForUsage + ->addMetric(METRIC_WEBHOOKS_FAILED, 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) + ; + } else { $webhook->setAttribute('attempts', 0); // Reset attempts on success $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); - $queueForUsage->addMetric(METRIC_WEBHOOKS_SENT, 1); + $queueForUsage + ->addMetric(METRIC_WEBHOOKS_SENT, 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_SENT), 1) + ; } $queueForUsage From dae5bf593ca9015ed555b11f7387392aca5692ce Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Tue, 24 Dec 2024 11:09:41 +0200 Subject: [PATCH 170/340] add webhooks usage stats --- src/Appwrite/Platform/Workers/Webhooks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index aa217dd6cf..50f64ea02d 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -171,7 +171,7 @@ class Webhooks extends Action $queueForUsage ->addMetric(METRIC_WEBHOOKS_FAILED, 1) ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) - ; + ; } else { From 452a58de94d1e08e1ab72c63ec35a47720688b29 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Tue, 24 Dec 2024 15:38:01 +0200 Subject: [PATCH 171/340] Reset matrics after enqueueing job via usage event --- src/Appwrite/Event/Usage.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index 161c251c8e..89e900d2ab 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -42,6 +42,7 @@ class Usage extends Event */ public function addMetric(string $key, int $value): self { + $this->metrics[] = [ 'key' => $key, 'value' => $value, @@ -62,10 +63,15 @@ class Usage extends Event } $client = new Client($this->queue, $this->connection); - return $client->enqueue([ + + $result = $client->enqueue([ 'project' => $this->getProject(), 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); + + $this->metrics = []; + + return $result; } } From 53860d2b96b21d4f98e67d4d4c6b7db182e3310f Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:07:53 +0000 Subject: [PATCH 172/340] chore: remove abuse cleanup --- src/Appwrite/Platform/Workers/Deletes.php | 31 +++-------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index f29b79e5db..9aaf19f412 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -7,7 +7,6 @@ use Appwrite\Certificates\Adapter as CertificatesAdapter; use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; -use Utopia\Abuse\Abuse; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -52,13 +51,12 @@ class Deletes extends Action ->inject('deviceForBuilds') ->inject('deviceForCache') ->inject('certificates') - ->inject('abuseRetention') ->inject('executionRetention') ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $abuseRetention, $executionRetention, $auditRetention, $log) + fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executionRetention, $auditRetention, $log) ); } @@ -66,7 +64,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, int $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -125,9 +123,6 @@ class Deletes extends Action $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); } break; - case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $timelimit, $abuseRetention); - break; case DELETE_TYPE_REALTIME: $this->deleteRealtimeUsage($dbForPlatform, $datetime); break; @@ -700,26 +695,6 @@ class Deletes extends Action ], $dbForPlatform); } - /** - * @param Database $dbForPlatform - * @param callable $getProjectDB - * @param int $abuseRetention - * @return void - * @throws Exception - */ - private function deleteAbuseLogs(Document $project, callable $timelimit, int $abuseRetention): void - { - $projectId = $project->getId(); - $timeLimit = $timelimit("", 0, 1); - $abuse = new Abuse($timeLimit); - - try { - $abuse->cleanup($abuseRetention); - } catch (DatabaseException $e) { - Console::error('Failed to delete abuse logs for project ' . $projectId . ': ' . $e->getMessage()); - } - } - /** * @param Database $dbForPlatform * @param callable $getProjectDB From 297826a62a3b8a0cd4078e82e122c94d789d83f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Fri, 27 Dec 2024 13:13:14 +0100 Subject: [PATCH 173/340] Fix git identity collisions --- app/config/collections.php | 33 +++++++++++++ app/controllers/api/vcs.php | 97 ++++++++++++------------------------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index a55ab1abd0..7a35dfe356 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -5417,6 +5417,39 @@ $consoleCollections = array_merge([ 'default' => false, 'array' => false, ], + [ + '$id' => ID::custom('personalAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('personalAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('personalRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], ], 'indexes' => [ diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 6e81c43ef8..eb3ef99495 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -355,53 +355,6 @@ App::get('/v1/vcs/github/callback') throw new Exception(Exception::PROJECT_NOT_FOUND, $error); } - $personalSlug = ''; - - // OAuth Authroization - if (!empty($code)) { - $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); - $accessToken = $oauth2->getAccessToken($code) ?? ''; - $refreshToken = $oauth2->getRefreshToken($code) ?? ''; - $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code) ?? ''; - $personalSlug = $oauth2->getUserSlug($accessToken) ?? ''; - $email = $oauth2->getUserEmail($accessToken); - $oauth2ID = $oauth2->getUserID($accessToken); - - // Makes sure this email is not already used in another identity - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('providerEmail', [$email]), - ]); - if (!$identity->isEmpty()) { - if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { - throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } else { - $identity = $dbForPlatform->createDocument('identities', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'userInternalId' => $user->getInternalId(), - 'userId' => $user->getId(), - 'provider' => 'github', - 'providerUid' => $oauth2ID, - 'providerEmail' => $email, - 'providerAccessToken' => $accessToken, - 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), - ])); - } - } - // Create / Update installation if (!empty($providerInstallationId)) { $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); @@ -416,6 +369,22 @@ App::get('/v1/vcs/github/callback') Query::equal('projectInternalId', [$projectInternalId]) ]); + $personal = false; + $refreshToken = null; + $accessToken = null; + $accessTokenExpiry = null; + + if (!empty($code)) { + $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); + $accessToken = $oauth2->getAccessToken($code) ?? ''; + $refreshToken = $oauth2->getRefreshToken($code) ?? ''; + $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code) ?? ''; + + $personalSlug = $oauth2->getUserSlug($accessToken) ?? ''; + + $personal = $personalSlug === $owner; + } + if ($installation->isEmpty()) { $teamId = $project->getAttribute('teamId', ''); @@ -433,14 +402,20 @@ App::get('/v1/vcs/github/callback') 'projectInternalId' => $projectInternalId, 'provider' => 'github', 'organization' => $owner, - 'personal' => $personalSlug === $owner + 'personal' => $personal, + 'personalRefreshToken' => $refreshToken, + 'personalAccessToken' => $accessToken, + 'personalAccessTokenExpiry' => $accessTokenExpiry, ]); $installation = $dbForPlatform->createDocument('installations', $installation); } else { $installation = $installation ->setAttribute('organization', $owner) - ->setAttribute('personal', $personalSlug === $owner); + ->setAttribute('personal', $personal) + ->setAttribute('personalRefreshToken', $refreshToken) + ->setAttribute('personalAccessToken', $accessToken) + ->setAttribute('personalAccessTokenExpiry', $accessTokenExpiry); $installation = $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } } else { @@ -720,17 +695,9 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if ($installation->getAttribute('personal', false) === true) { $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('provider', ['github']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); + $accessToken = $installation->getAttribute('personalAccessToken'); + $refreshToken = $installation->getAttribute('personalRefreshToken'); + $accessTokenExpiry = $installation->getAttribute('personalAccessTokenExpiry'); $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); if ($isExpired) { @@ -745,12 +712,12 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, "Another request is currently refreshing OAuth token. Please try again."); } - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); + $installation = $installation + ->setAttribute('personalAccessToken', $accessToken) + ->setAttribute('personalRefreshToken', $refreshToken) + ->setAttribute('personalAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } try { From fcb517e679fb594220142713f3922604995ea6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Fri, 27 Dec 2024 13:32:22 +0100 Subject: [PATCH 174/340] Fix type error --- app/controllers/api/vcs.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index eb3ef99495..f90db24e98 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -376,12 +376,12 @@ App::get('/v1/vcs/github/callback') if (!empty($code)) { $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); + $accessToken = $oauth2->getAccessToken($code) ?? ''; $refreshToken = $oauth2->getRefreshToken($code) ?? ''; - $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code) ?? ''; + $accessTokenExpiry = DateTime::addSeconds(new \DateTime(), \intval($oauth2->getAccessTokenExpiry($code))); $personalSlug = $oauth2->getUserSlug($accessToken) ?? ''; - $personal = $personalSlug === $owner; } From 769772a0a840911db1995464897567b4b253650e Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 27 Dec 2024 20:30:03 +0000 Subject: [PATCH 175/340] fix: remove abuse delete trigger --- src/Appwrite/Platform/Tasks/Maintenance.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index 55f4f25843..c789cbdaac 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -66,7 +66,6 @@ class Maintenance extends Action { $this->notifyDeleteTargets($queueForDeletes); $this->notifyDeleteExecutionLogs($queueForDeletes); - $this->notifyDeleteAbuseLogs($queueForDeletes); $this->notifyDeleteAuditLogs($queueForDeletes); $this->notifyDeleteUsageStats($usageStatsRetentionHourly, $queueForDeletes); $this->notifyDeleteExpiredSessions($queueForDeletes); @@ -106,13 +105,6 @@ class Maintenance extends Action ->trigger(); } - private function notifyDeleteAbuseLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_ABUSE) - ->trigger(); - } - private function notifyDeleteAuditLogs(Delete $queueForDeletes): void { $queueForDeletes From 4691407a7abe31270d38cebdf07a24faef3fdc4c Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 27 Dec 2024 20:41:30 +0000 Subject: [PATCH 176/340] chore: bump utopia-php/abuse to 0.46.0 --- composer.json | 2 +- composer.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index 2879993d3f..e49948977b 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.45.*", + "utopia-php/abuse": "0.46.*", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", diff --git a/composer.lock b/composer.lock index 5bce56a022..083456a0d4 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": "db3b63ba1be2561ee4a112e5b9c6bd53", + "content-hash": "786a6c2f9aa130c673f8a39a18a28e3c", "packages": [ { "name": "adhocore/jwt", @@ -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": { @@ -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": { @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.45.0", + "version": "0.46.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "54a58355df1eb26c9be7834738debe6754e5581d" + "reference": "bef426a9a28b3e71b08216bcbe310455f588c11b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/54a58355df1eb26c9be7834738debe6754e5581d", - "reference": "54a58355df1eb26c9be7834738debe6754e5581d", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/bef426a9a28b3e71b08216bcbe310455f588c11b", + "reference": "bef426a9a28b3e71b08216bcbe310455f588c11b", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.45.0" + "source": "https://github.com/utopia-php/abuse/tree/0.46.0" }, - "time": "2024-12-20T16:18:52+00:00" + "time": "2024-12-27T17:46:08+00:00" }, { "name": "utopia-php/analytics", From 58fd0d35bd13d034c79efc2d2ee6b4210ac75955 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Sun, 29 Dec 2024 17:47:52 +0200 Subject: [PATCH 177/340] database crud usage addition --- src/Appwrite/Event/Usage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index 89e900d2ab..d2e302f82b 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -69,7 +69,7 @@ class Usage extends Event 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); - + var_dump($this->metrics); $this->metrics = []; return $result; From c23af8168becf391dcc8403d10d727fe553fdeab Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Sun, 29 Dec 2024 17:48:05 +0200 Subject: [PATCH 178/340] database crud usage addition --- app/controllers/api/databases.php | 158 +++++++++++++++++++----------- app/init.php | 2 + 2 files changed, 104 insertions(+), 56 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index aad072c50a..80bc72c4b7 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2885,7 +2885,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(function () use ($queueForUsage, $dbForProject, $databaseId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('databases', $databaseId); + }); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -2895,6 +2899,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2981,8 +2986,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedCollection = Authorization::skip(function () use ($relatedCollectionId, $dbForProject, $queueForUsage) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + } ); foreach ($relations as &$relation) { @@ -2995,8 +3002,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relation = new Document($relation); } if ($relation instanceof Document) { - $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + $current = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); + } ); if ($current->isEmpty()) { @@ -3028,6 +3037,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); + $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); } catch (StructureException $e) { throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (DuplicateException $e) { @@ -3037,7 +3047,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3057,8 +3067,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + } ); foreach ($related as $relation) { @@ -3116,8 +3128,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('response') ->inject('dbForProject') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) { + ->inject('queueForUsage') + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3126,6 +3141,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3155,7 +3171,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(function() use ($dbForProject, $queueForUsage, $collection, $database, $documentId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + }); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -3165,10 +3184,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { + $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage): bool { if ($document->isEmpty()) { return false; } @@ -3195,7 +3217,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(function() use ($dbForProject, $queueForUsage, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + }); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -3274,8 +3299,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('response') ->inject('dbForProject') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) { + ->inject('queueForUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3284,7 +3312,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + }); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3293,6 +3324,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen try { $queries = Query::parseQueries($queries); $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { @@ -3304,7 +3336,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { if ($document->isEmpty()) { return; } @@ -3328,8 +3360,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + } ); foreach ($related as $relation) { @@ -3481,7 +3515,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('dbForProject') ->inject('queueForEvents') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode) { + ->inject('queueForUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Usage $queueForUsage) { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -3489,7 +3524,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(function () use($queueForUsage, $dbForProject, $databaseId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('databases', $databaseId); + }); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3498,7 +3536,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $collectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + }); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3506,7 +3547,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + }); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3548,7 +3592,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, $queueForUsage) { $relationships = \array_filter( $collection->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP @@ -3570,9 +3614,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) - ); + $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + }); foreach ($relations as &$relation) { // If the relation is an array it can be either update or create a child document. @@ -3585,17 +3630,15 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relation = new Document($relation); } if ($relation instanceof Document) { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), - $relation->getId() - )); + $oldDocument = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); + }); + $relation->removeAttribute('$collectionId'); $relation->removeAttribute('$databaseId'); // Attribute $collection is required for Utopia. - $relation->setAttribute( - '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() - ); + $relation->setAttribute('$collection', 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); if ($oldDocument->isEmpty()) { if (isset($relation['$id']) && $relation['$id'] === 'unique()') { @@ -3617,14 +3660,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection($collection, $newDocument); try { - $document = $dbForProject->withRequestTimestamp( - $requestTimestamp, - fn () => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $document->getId(), - $newDocument - ) - ); + $document = $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $document, $newDocument) { + $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); + return $dbForProject->updateDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document->getId(), $newDocument); + }); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (DuplicateException) { @@ -3636,7 +3675,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3656,9 +3695,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) - ); + $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + }); foreach ($related as $relation) { if ($relation instanceof Document) { @@ -3720,6 +3760,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3728,32 +3769,36 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + }); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + }); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { - $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $documentId - ); + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); + $dbForProject->deleteDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); }); } catch (NotFoundException $e) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3773,9 +3818,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) - ); + $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + }); foreach ($related as $relation) { if ($relation instanceof Document) { diff --git a/app/init.php b/app/init.php index c6847610c2..d5b8e4b235 100644 --- a/app/init.php +++ b/app/init.php @@ -232,6 +232,8 @@ const API_KEY_DYNAMIC = 'dynamic'; // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; +const METRIC_DATABASE_API_READ = 'database.api.events.read'; +const METRIC_DATABASE_API_WRITE = 'database.api.events.write'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; From 025c9aeeb297f6a0a96df401c6d0281321d17fb5 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Sun, 29 Dec 2024 17:53:45 +0200 Subject: [PATCH 179/340] database crud usage addition --- src/Appwrite/Event/Usage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index d2e302f82b..89e900d2ab 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -69,7 +69,7 @@ class Usage extends Event 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); - var_dump($this->metrics); + $this->metrics = []; return $result; From 8e17fc69b371861ee04da7e98a99fac294b42588 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Sun, 29 Dec 2024 17:57:29 +0200 Subject: [PATCH 180/340] database crud usage addition --- app/controllers/api/databases.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 80bc72c4b7..b98df1382f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2898,8 +2898,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId){ + $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + }); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); From dd13e8b3cf705be22540b93ff3be493a771fc399 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Sun, 29 Dec 2024 18:02:19 +0200 Subject: [PATCH 181/340] database crud usage addition --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index b98df1382f..4275ab52ae 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3219,7 +3219,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function() use ($dbForProject, $queueForUsage, $database, $relatedCollectionId) { + $relatedCollection = Authorization::skip(function() use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); }); From 26bac5a2ea05cc76b49a79f848953a72d4125ade Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Mon, 30 Dec 2024 09:00:52 +0000 Subject: [PATCH 182/340] Remove firebase OAuth API endpoints --- app/config/specs/open-api3-latest-client.json | 6 +- .../specs/open-api3-latest-console.json | 415 +++------------ app/config/specs/open-api3-latest-server.json | 102 ++-- app/config/specs/swagger2-latest-client.json | 6 +- app/config/specs/swagger2-latest-console.json | 430 +++------------- app/config/specs/swagger2-latest-server.json | 102 ++-- app/controllers/api/migrations.php | 474 +----------------- src/Appwrite/Auth/OAuth2/Firebase.php | 389 -------------- 8 files changed, 239 insertions(+), 1685 deletions(-) delete mode 100644 src/Appwrite/Auth/OAuth2/Firebase.php diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index d948a101f2..af7303c985 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -5766,7 +5766,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -5851,7 +5851,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index fb01509ecd..6878909f64 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -9488,7 +9488,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10145,7 +10146,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13673,7 +13675,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13751,7 +13753,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -13897,7 +13899,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -14045,7 +14047,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14202,7 +14204,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14361,7 +14363,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14472,7 +14474,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -14586,7 +14588,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14641,7 +14643,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14705,7 +14707,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -14782,7 +14784,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -14859,7 +14861,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14937,7 +14939,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -15044,7 +15046,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15154,7 +15156,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15241,7 +15243,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15331,7 +15333,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15448,7 +15450,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15568,7 +15570,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15665,7 +15667,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15765,7 +15767,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -15872,7 +15874,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15982,7 +15984,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16127,7 +16129,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16274,7 +16276,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16371,7 +16373,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16471,7 +16473,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16568,7 +16570,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -16668,7 +16670,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16765,7 +16767,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16865,7 +16867,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16962,7 +16964,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -17062,7 +17064,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17117,7 +17119,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17181,7 +17183,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17258,7 +17260,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17335,7 +17337,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17411,7 +17413,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17496,7 +17498,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17558,7 +17560,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -17637,7 +17639,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -17701,7 +17703,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17778,7 +17780,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17864,7 +17866,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17956,7 +17958,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -18021,7 +18023,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18098,7 +18100,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18264,7 +18266,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18339,7 +18341,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "tags": [ "migrations" @@ -18359,7 +18361,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18415,177 +18417,6 @@ } } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File" - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migration" - } - } - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-migration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "requestBody": { - "content": { - "application\/json": { - "schema": { - "type": "object", - "properties": { - "resources": { - "type": "array", - "description": "List of resources to migrate", - "x-example": null, - "items": { - "type": "string" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - } - } - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/firebaseProjectList" - } - } - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -18608,7 +18439,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -18660,80 +18491,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migrationReport" - } - } - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "schema": { - "type": "string", - "x-example": "<PROJECT_ID>" - }, - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -18756,7 +18513,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -18869,7 +18626,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -19004,7 +18761,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19111,7 +18868,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19237,7 +18994,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19297,7 +19054,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19350,7 +19107,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -32749,30 +32506,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase Projects List", - "type": "object", - "properties": { - "total": { - "type": "integer", - "description": "Total number of projects documents that matched your query.", - "x-example": 5, - "format": "int32" - }, - "projects": { - "type": "array", - "description": "List of projects.", - "items": { - "$ref": "#\/components\/schemas\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35109,7 +34842,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -38707,26 +38440,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "securitySchemes": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 1504322456..8900d6ddf2 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8596,7 +8596,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9019,7 +9020,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12527,7 +12529,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12606,7 +12608,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12753,7 +12755,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -12902,7 +12904,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -13060,7 +13062,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13220,7 +13222,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13332,7 +13334,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -13447,7 +13449,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13503,7 +13505,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13568,7 +13570,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13646,7 +13648,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -13724,7 +13726,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -13803,7 +13805,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13911,7 +13913,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14022,7 +14024,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14110,7 +14112,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14201,7 +14203,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14319,7 +14321,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14440,7 +14442,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14538,7 +14540,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14639,7 +14641,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -14747,7 +14749,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14858,7 +14860,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15004,7 +15006,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15152,7 +15154,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15250,7 +15252,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15351,7 +15353,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15449,7 +15451,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15550,7 +15552,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -15648,7 +15650,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15749,7 +15751,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -15847,7 +15849,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -15948,7 +15950,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -16004,7 +16006,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16069,7 +16071,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16147,7 +16149,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16225,7 +16227,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16302,7 +16304,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16388,7 +16390,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16451,7 +16453,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16531,7 +16533,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -16596,7 +16598,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -16674,7 +16676,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -16761,7 +16763,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -16855,7 +16857,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -16921,7 +16923,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -25746,7 +25748,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 3ac70ffe28..77025ec042 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -5981,7 +5981,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -6070,7 +6070,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 25c0c289b3..0ef937050c 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -9610,7 +9610,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10286,7 +10287,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13890,7 +13892,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13967,7 +13969,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -14127,7 +14129,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -14284,7 +14286,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14459,7 +14461,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14631,7 +14633,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14751,7 +14753,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -14869,7 +14871,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14928,7 +14930,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14992,7 +14994,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -15068,7 +15070,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -15144,7 +15146,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -15221,7 +15223,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -15338,7 +15340,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15453,7 +15455,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15546,7 +15548,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15637,7 +15639,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15766,7 +15768,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15893,7 +15895,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15998,7 +16000,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -16101,7 +16103,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16218,7 +16220,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -16333,7 +16335,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16494,7 +16496,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16652,7 +16654,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16757,7 +16759,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16860,7 +16862,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16965,7 +16967,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -17068,7 +17070,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17173,7 +17175,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -17276,7 +17278,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17381,7 +17383,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -17484,7 +17486,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17543,7 +17545,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17607,7 +17609,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17683,7 +17685,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17759,7 +17761,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17834,7 +17836,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17926,7 +17928,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17988,7 +17990,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -18071,7 +18073,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -18135,7 +18137,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -18211,7 +18213,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -18294,7 +18296,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -18386,7 +18388,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -18453,7 +18455,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18528,7 +18530,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18699,7 +18701,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18767,7 +18769,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "consumes": [ "application\/json" @@ -18789,7 +18791,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18847,192 +18849,6 @@ ] } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File", - "schema": { - "type": "file" - } - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "schema": { - "$ref": "#\/definitions\/migration" - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-migration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "payload", - "in": "body", - "schema": { - "type": "object", - "properties": { - "resources": { - "type": "array", - "description": "List of resources to migrate", - "default": null, - "x-example": null, - "items": { - "type": "string" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "default": null, - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - ] - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "schema": { - "$ref": "#\/definitions\/firebaseProjectList" - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -19057,7 +18873,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -19106,79 +18922,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "schema": { - "$ref": "#\/definitions\/migrationReport" - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "type": "array", - "collectionFormat": "multi", - "items": { - "type": "string" - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "type": "string", - "x-example": "<PROJECT_ID>", - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -19203,7 +18946,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -19326,7 +19069,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -19448,7 +19191,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19564,7 +19307,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19679,7 +19422,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19739,7 +19482,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19794,7 +19537,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -33250,31 +32993,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase Projects List", - "type": "object", - "properties": { - "total": { - "type": "integer", - "description": "Total number of projects documents that matched your query.", - "x-example": 5, - "format": "int32" - }, - "projects": { - "type": "array", - "description": "List of projects.", - "items": { - "type": "object", - "$ref": "#\/definitions\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35618,7 +35336,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -39274,26 +38992,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "externalDocs": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 68bcf268fb..f5b1f24a22 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8720,7 +8720,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9166,7 +9167,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12752,7 +12754,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12830,7 +12832,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12991,7 +12993,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -13149,7 +13151,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -13325,7 +13327,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13498,7 +13500,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13619,7 +13621,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -13738,7 +13740,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13798,7 +13800,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13863,7 +13865,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13940,7 +13942,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -14017,7 +14019,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14095,7 +14097,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14213,7 +14215,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14329,7 +14331,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14423,7 +14425,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14515,7 +14517,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14645,7 +14647,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14773,7 +14775,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14879,7 +14881,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14983,7 +14985,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -15101,7 +15103,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15217,7 +15219,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15379,7 +15381,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15538,7 +15540,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15644,7 +15646,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15748,7 +15750,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15854,7 +15856,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15958,7 +15960,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16064,7 +16066,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16168,7 +16170,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16274,7 +16276,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -16378,7 +16380,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -16438,7 +16440,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16503,7 +16505,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16580,7 +16582,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16657,7 +16659,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16733,7 +16735,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16826,7 +16828,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16889,7 +16891,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16973,7 +16975,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -17038,7 +17040,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17115,7 +17117,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17199,7 +17201,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17293,7 +17295,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -17361,7 +17363,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -26233,7 +26235,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 3abd1db016..29e46505f5 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -1,17 +1,12 @@ <?php -use Appwrite\Auth\OAuth2\Firebase as OAuth2Firebase; use Appwrite\Event\Event; use Appwrite\Event\Migration; use Appwrite\Extend\Exception; -use Appwrite\Permission; -use Appwrite\Role; use Appwrite\Utopia\Database\Validator\Queries\Migrations; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; @@ -22,9 +17,7 @@ use Utopia\Migration\Sources\Appwrite; use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; -use Utopia\System\System; use Utopia\Validator\ArrayList; -use Utopia\Validator\Host; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -87,112 +80,9 @@ App::post('/v1/migrations/appwrite') ->dynamic($migration, Response::MODEL_MIGRATION); }); -App::post('/v1/migrations/firebase/oauth') - ->groups(['api', 'migrations']) - ->desc('Migrate Firebase data (OAuth)') - ->label('scope', 'migrations.write') - ->label('event', 'migrations.[migrationId].create') - ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseOAuthMigration') - ->label('sdk.description', '/docs/references/migrations/migration-firebase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) - ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') - ->param('projectId', '', new Text(65536), 'Project ID of the Firebase Project') - ->inject('response') - ->inject('dbForProject') - ->inject('dbForPlatform') - ->inject('project') - ->inject('user') - ->inject('queueForEvents') - ->inject('queueForMigrations') - ->inject('request') - ->action(function (array $resources, string $projectId, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Document $user, Event $queueForEvents, Migration $queueForMigrations, Request $request) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - $firebase->refreshTokens($refreshToken); - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } - - if ($identity->getAttribute('secrets')) { - $serviceAccount = $identity->getAttribute('secrets'); - } else { - $firebase->cleanupServiceAccounts($accessToken, $projectId); - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); - $identity = $identity - ->setAttribute('secrets', json_encode($serviceAccount)); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } - - $migration = $dbForProject->createDocument('migrations', new Document([ - '$id' => ID::unique(), - 'status' => 'pending', - 'stage' => 'init', - 'source' => Firebase::getName(), - 'destination' => Appwrite::getName(), - 'credentials' => [ - 'serviceAccount' => json_encode($serviceAccount), - ], - 'resources' => $resources, - 'statusCounters' => '{}', - 'resourceData' => '{}', - 'errors' => [] - ])); - - $queueForEvents->setParam('migrationId', $migration->getId()); - - // Trigger Transfer - $queueForMigrations - ->setMigration($migration) - ->setProject($project) - ->setUser($user) - ->trigger(); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($migration, Response::MODEL_MIGRATION); - }); - App::post('/v1/migrations/firebase') ->groups(['api', 'migrations']) - ->desc('Migrate Firebase data (Service Account)') + ->desc('Migrate Firebase data') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') @@ -547,368 +437,6 @@ App::get('/v1/migrations/firebase/report') ->dynamic(new Document($report), Response::MODEL_MIGRATION_REPORT); }); -App::get('/v1/migrations/firebase/report/oauth') - ->groups(['api', 'migrations']) - ->desc('Generate a report on Firebase data using OAuth') - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getFirebaseReportOAuth') - ->label('sdk.description', '/docs/references/migrations/migration-firebase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) - ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') - ->param('projectId', '', new Text(65536), 'Project ID') - ->inject('response') - ->inject('request') - ->inject('user') - ->inject('dbForPlatform') - ->action(function (array $resources, string $projectId, Response $response, Request $request, Document $user, Database $dbForPlatform) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - if (System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - $firebase->refreshTokens($refreshToken); - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } - - // Get Service Account - if ($identity->getAttribute('secrets')) { - $serviceAccount = $identity->getAttribute('secrets'); - } else { - $firebase->cleanupServiceAccounts($accessToken, $projectId); - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); - $identity = $identity - ->setAttribute('secrets', json_encode($serviceAccount)); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } - - $firebase = new Firebase($serviceAccount); - - try { - $report = $firebase->report($resources); - } catch (\Throwable $e) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Source Error: ' . $e->getMessage()); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic(new Document($report), Response::MODEL_MIGRATION_REPORT); - }); - -App::get('/v1/migrations/firebase/connect') - ->desc('Authorize with Firebase') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseAuth') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') - ->label('sdk.hide', true) - ->param('redirect', '', fn ($clients) => new Host($clients), 'URL to redirect back to your Firebase authorization. Only console hostnames are allowed.', true, ['clients']) - ->param('projectId', '', new UID(), 'Project ID') - ->inject('response') - ->inject('request') - ->inject('user') - ->inject('dbForPlatform') - ->action(function (string $redirect, string $projectId, Response $response, Request $request, Document $user, Database $dbForPlatform) { - $state = \json_encode([ - 'projectId' => $projectId, - 'redirect' => $redirect, - ]); - - $prefs = $user->getAttribute('prefs', []); - $prefs['migrationState'] = $state; - $user->setAttribute('prefs', $prefs); - $dbForPlatform->updateDocument('users', $user->getId(), $user); - - $oauth2 = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - $url = $oauth2->getLoginURL(); - - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($url); - }); - -App::get('/v1/migrations/firebase/redirect') - ->desc('Capture and receive data on Firebase authorization') - ->groups(['api', 'migrations']) - ->label('scope', 'public') - ->label('error', __DIR__ . '/../../views/general/error.phtml') - ->param('code', '', new Text(2048), 'OAuth2 code. This is a temporary code that the will be later exchanged for an access token.', true) - ->inject('user') - ->inject('project') - ->inject('request') - ->inject('response') - ->inject('dbForPlatform') - ->action(function (string $code, Document $user, Document $project, Request $request, Response $response, Database $dbForPlatform) { - $state = $user['prefs']['migrationState'] ?? '{}'; - $prefs['migrationState'] = ''; - $user->setAttribute('prefs', $prefs); - $dbForPlatform->updateDocument('users', $user->getId(), $user); - - if (empty($state)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Installation requests from organisation members for the Appwrite Google App are currently unsupported.'); - } - - $state = \json_decode($state, true); - $redirect = $state['redirect'] ?? ''; - $projectId = $state['projectId'] ?? ''; - - $project = $dbForPlatform->getDocument('projects', $projectId); - - if (empty($redirect)) { - $redirect = $request->getProtocol() . '://' . $request->getHostname() . '/console/project-$projectId/settings/migrations'; - } - - if ($project->isEmpty()) { - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($redirect); - - return; - } - - // OAuth Authroization - if (!empty($code)) { - $oauth2 = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $accessToken = $oauth2->getAccessToken($code); - $refreshToken = $oauth2->getRefreshToken($code); - $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code); - $email = $oauth2->getUserEmail($accessToken); - $oauth2ID = $oauth2->getUserID($accessToken); - - if (empty($accessToken)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token.'); - } - - if (empty($refreshToken)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get refresh token.'); - } - - if (empty($accessTokenExpiry)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token expiry.'); - } - - // Makes sure this email is not already used in another identity - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('providerEmail', [$email]), - ]); - - if (!$identity->isEmpty()) { - if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { - throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); - } - } - - if (!$identity->isEmpty()) { - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } else { - $identity = $dbForPlatform->createDocument('identities', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'userInternalId' => $user->getInternalId(), - 'userId' => $user->getId(), - 'provider' => 'firebase', - 'providerUid' => $oauth2ID, - 'providerEmail' => $email, - 'providerAccessToken' => $accessToken, - 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), - ])); - } - } else { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Missing OAuth2 code.'); - } - - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($redirect); - }); - -App::get('/v1/migrations/firebase/projects') - ->desc('List Firebase projects') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'listFirebaseProjects') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_FIREBASE_PROJECT_LIST) - ->inject('user') - ->inject('response') - ->inject('project') - ->inject('dbForPlatform') - ->inject('request') - ->action(function (Document $user, Response $response, Document $project, Database $dbForPlatform, Request $request) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - if (System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - try { - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - try { - $firebase->refreshTokens($refreshToken); - } catch (\Throwable $e) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForPlatform->updateDocument('identities', $identity->getId(), $identity); - } - - $projects = $firebase->getProjects($accessToken); - - $output = []; - foreach ($projects as $project) { - $output[] = [ - 'displayName' => $project['displayName'], - 'projectId' => $project['projectId'], - ]; - } - } catch (\Throwable $e) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $response->dynamic(new Document([ - 'projects' => $output, - 'total' => count($output), - ]), Response::MODEL_MIGRATION_FIREBASE_PROJECT_LIST); - }); - -App::get('/v1/migrations/firebase/deauthorize') - ->desc('Revoke Appwrite\'s authorization to access Firebase projects') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'deleteFirebaseAuth') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->inject('user') - ->inject('response') - ->inject('dbForPlatform') - ->action(function (Document $user, Response $response, Database $dbForPlatform) { - $identity = $dbForPlatform->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND - } - - $dbForPlatform->deleteDocument('identities', $identity->getId()); - - $response->noContent(); - }); - App::get('/v1/migrations/supabase/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Supabase Data') diff --git a/src/Appwrite/Auth/OAuth2/Firebase.php b/src/Appwrite/Auth/OAuth2/Firebase.php deleted file mode 100644 index 0e2859e32c..0000000000 --- a/src/Appwrite/Auth/OAuth2/Firebase.php +++ /dev/null @@ -1,389 +0,0 @@ -<?php - -namespace Appwrite\Auth\OAuth2; - -use Appwrite\Auth\OAuth2; - -class Firebase extends OAuth2 -{ - /** - * @var array - */ - protected array $user = []; - - /** - * @var array - */ - protected array $tokens = []; - - /** - * @var array - */ - protected array $scopes = [ - 'https://www.googleapis.com/auth/firebase', - 'https://www.googleapis.com/auth/datastore', - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/identitytoolkit', - 'https://www.googleapis.com/auth/userinfo.profile' - ]; - - /** - * @var array - */ - protected array $iamPermissions = [ - // Database - 'datastore.databases.get', - 'datastore.databases.list', - 'datastore.entities.get', - 'datastore.entities.list', - 'datastore.indexes.get', - 'datastore.indexes.list', - // Generic Firebase permissions - 'firebase.projects.get', - - // Auth - 'firebaseauth.configs.get', - 'firebaseauth.configs.getHashConfig', - 'firebaseauth.configs.getSecret', - 'firebaseauth.users.get', - 'identitytoolkit.tenants.get', - 'identitytoolkit.tenants.list', - - // IAM Assignment - 'iam.serviceAccounts.list', - - // Storage - 'storage.buckets.get', - 'storage.buckets.list', - 'storage.objects.get', - 'storage.objects.list' - ]; - - /** - * @return string - */ - public function getName(): string - { - return 'firebase'; - } - - /** - * @return string - */ - public function getLoginURL(): string - { - return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ - 'access_type' => 'offline', - 'client_id' => $this->appID, - 'redirect_uri' => $this->callback, - 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), - 'response_type' => 'code', - 'prompt' => 'consent', - ]); - } - - /** - * @param string $code - * - * @return array - */ - protected function getTokens(string $code): array - { - if (empty($this->tokens)) { - $response = $this->request( - 'POST', - 'https://oauth2.googleapis.com/token', - [], - \http_build_query([ - 'client_id' => $this->appID, - 'redirect_uri' => $this->callback, - 'client_secret' => $this->appSecret, - 'code' => $code, - 'grant_type' => 'authorization_code' - ]) - ); - - $this->tokens = \json_decode($response, true); - } - - return $this->tokens; - } - - /** - * @param string $refreshToken - * - * @return array - */ - public function refreshTokens(string $refreshToken): array - { - $response = $this->request( - 'POST', - 'https://oauth2.googleapis.com/token', - [], - \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken - ]) - ); - - $output = []; - \parse_str($response, $output); - $this->tokens = $output; - - if (empty($this->tokens['refresh_token'])) { - $this->tokens['refresh_token'] = $refreshToken; - } - - return $this->tokens; - } - - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserID(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['id'] ?? ''; - } - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserEmail(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['email'] ?? ''; - } - - - /** - * Check if the OAuth email is verified - * - * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user - * - * @param string $accessToken - * - * @return bool - */ - public function isEmailVerified(string $accessToken): bool - { - $user = $this->getUser($accessToken); - - if ($user['verified'] ?? false) { - return true; - } - - return false; - } - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserName(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['name'] ?? ''; - } - - /** - * @param string $accessToken - * - * @return array - */ - protected function getUser(string $accessToken) - { - if (empty($this->user)) { - $response = $this->request( - 'GET', - 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken), - [], - ); - - $this->user = \json_decode($response, true); - } - - return $this->user; - } - - public function getProjects(string $accessToken): array - { - $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer ' . \urlencode($accessToken)]); - - $projects = \json_decode($projects, true); - - return $projects['results']; - } - - /* - Be careful with the setIAMPolicy method, it will overwrite all existing policies - **/ - public function assignIAMRole(string $accessToken, string $email, string $projectId, array $role) - { - // Get IAM Roles - $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':getIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ]); - - $iamRoles = \json_decode($iamRoles, true); - - $iamRoles['bindings'][] = [ - 'role' => $role['name'], - 'members' => [ - 'serviceAccount:' . $email - ] - ]; - - // Set IAM Roles - $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':setIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ], \json_encode([ - 'policy' => $iamRoles - ])); - } - - private function generateRandomString($length = 10): string - { - $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[random_int(0, $charactersLength - 1)]; - } - return $randomString; - } - - private function createCustomRole(string $accessToken, string $projectId): array - { - // Check if role already exists - try { - $role = $this->request('GET', 'https://iam.googleapis.com/v1/projects/' . $projectId . '/roles/appwriteMigrations', [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . \urlencode($accessToken), - ]); - - $role = \json_decode($role, true); - - return $role; - } catch (\Throwable $e) { - if ($e->getCode() !== 404) { - throw $e; - } - } - - // Create role if doesn't exist or isn't correct - $role = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/roles/', - [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . \urlencode($accessToken), - ], - \json_encode( - [ - 'roleId' => 'appwriteMigrations', - 'role' => [ - 'title' => 'Appwrite Migrations', - 'description' => 'A helper role for Appwrite Migrations', - 'includedPermissions' => $this->iamPermissions, - 'stage' => 'GA' - ] - ] - ) - ); - - return json_decode($role, true); - } - - public function createServiceAccount(string $accessToken, string $projectId): array - { - // Create Service Account - $uid = $this->generateRandomString(); - - $response = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ], - \json_encode([ - 'accountId' => 'appwrite-' . $uid, - 'serviceAccount' => [ - 'displayName' => 'Appwrite Migrations ' . $uid - ] - ]) - ); - - $response = json_decode($response, true); - - // Create and assign IAM Roles - $role = $this->createCustomRole($accessToken, $projectId); - - \sleep(1); // Wait for IAM to propagate changes. - - $this->assignIAMRole($accessToken, $response['email'], $projectId, $role); - - // Create Service Account Key - $responseKey = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - - $responseKey = json_decode($responseKey, true); - - return json_decode(base64_decode($responseKey['privateKeyData']), true); - } - - public function cleanupServiceAccounts(string $accessToken, string $projectId) - { - // List Service Accounts - $response = $this->request( - 'GET', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - - $response = json_decode($response, true); - - if (empty($response['accounts'])) { - return false; - } - - foreach ($response['accounts'] as $account) { - if (strpos($account['email'], 'appwrite-') !== false) { - $this->request( - 'DELETE', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $account['email'], - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - } - } - - return true; - } -} From dd0658de1999e7b00c2bf4135507e919369039fa Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 30 Dec 2024 11:26:11 +0000 Subject: [PATCH 183/340] chore: bump versions --- app/config/platforms.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 1470bd1364..167e55651c 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '13.1.0', + 'version' => '13.1.1', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -134,7 +134,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.5.0', + 'version' => '0.6.0', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, From 8c7520329868b892e3d9984bba54cd50b4581ee0 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 30 Dec 2024 11:59:19 +0000 Subject: [PATCH 184/340] chore: bump sdk generator --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index d8bee998c3..e44dd0bffc 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.39.27", + "appwrite/sdk-generator": "0.39.28", "phpunit/phpunit": "9.5.20", "swoole/ide-helper": "5.1.2", "textalk/websocket": "1.5.7", diff --git a/composer.lock b/composer.lock index 419201d5f7..ce5f358619 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": "9712ceefbca8a06dfcf5e003f9c92171", + "content-hash": "6b136b5490c0d5d331eac0d70bb3e198", "packages": [ { "name": "adhocore/jwt", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.27", + "version": "0.39.28", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849" + "reference": "6ff467858fe418e364460da905139216570a5d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/27d8ecde30e40cbfe1124cc0430c406d3e144849", - "reference": "27d8ecde30e40cbfe1124cc0430c406d3e144849", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6ff467858fe418e364460da905139216570a5d5e", + "reference": "6ff467858fe418e364460da905139216570a5d5e", "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.27" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.28" }, - "time": "2024-12-16T11:32:02+00:00" + "time": "2024-12-30T11:17:25+00:00" }, { "name": "doctrine/annotations", From ba04a7760b21579cd6dd534a894cfd9330180260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Mon, 30 Dec 2024 14:43:28 +0100 Subject: [PATCH 185/340] Backwards-compatibility --- app/controllers/api/vcs.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index f90db24e98..f24a0d97fe 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -699,6 +699,20 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') $refreshToken = $installation->getAttribute('personalRefreshToken'); $accessTokenExpiry = $installation->getAttribute('personalAccessTokenExpiry'); + if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { + $identity = $dbForPlatform->findOne('identities', [ + Query::equal('provider', ['github']), + Query::equal('userInternalId', [$user->getInternalId()]), + ]); + if ($identity->isEmpty()) { + throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); + } + + $accessToken = $accessToken ?? $identity->getAttribute('providerAccessToken'); + $refreshToken = $refreshToken ?? $identity->getAttribute('providerRefreshToken'); + $accessTokenExpiry = $accessTokenExpiry ?? $identity->getAttribute('providerAccessTokenExpiry'); + } + $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); if ($isExpired) { $oauth2->refreshTokens($refreshToken); From d3b764a9e2e718b93a845979deca7a29ddeb8bd4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Mon, 30 Dec 2024 15:10:27 +0000 Subject: [PATCH 186/340] Set base specification CPUs to 0.5 again --- app/config/runtimes/specifications.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/runtimes/specifications.php b/app/config/runtimes/specifications.php index 68880f4d4e..d3625db8a2 100644 --- a/app/config/runtimes/specifications.php +++ b/app/config/runtimes/specifications.php @@ -6,7 +6,7 @@ return [ Specification::S_05VCPU_512MB => [ 'slug' => Specification::S_05VCPU_512MB, 'memory' => 512, - 'cpus' => 1 // TODO: revert this, it's a temporary change to test function performance. + 'cpus' => 0.5 ], Specification::S_1VCPU_512MB => [ 'slug' => Specification::S_1VCPU_512MB, From 4ce919c8c6ffcf55af196637399c4e1b90cc239e Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Tue, 31 Dec 2024 23:11:00 +0000 Subject: [PATCH 187/340] chore: update composer.lock after merge --- composer.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/composer.lock b/composer.lock index 361dfe4c84..aad4e039fa 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": "6b136b5490c0d5d331eac0d70bb3e198", + "content-hash": "4ce4526b10d26830d8f9eaf55e40135c", "packages": [ { "name": "adhocore/jwt", @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.1", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" + "reference": "339ba21476eb184290361542f732ad12c97591ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", + "reference": "339ba21476eb184290361542f732ad12c97591ec", "shasum": "" }, "require": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.1" + "source": "https://github.com/symfony/http-client/tree/v7.2.2" }, "funding": [ { @@ -2544,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2024-12-30T18:35:15+00:00" }, { "name": "symfony/http-client-contracts", @@ -5126,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": { @@ -5146,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" @@ -5188,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", @@ -7735,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": { @@ -7779,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": [ { @@ -7795,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", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From c7b2a90a0c4adffc12882ef5cf91477955a0b7ff Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Thu, 2 Jan 2025 10:18:47 +0530 Subject: [PATCH 188/340] feat: split collections. --- app/config/collections.php | 6156 +-------------------------- app/config/collections/bucket.php | 270 ++ app/config/collections/common.php | 2357 ++++++++++ app/config/collections/database.php | 126 + app/config/collections/platform.php | 1534 +++++++ app/config/collections/project.php | 1873 ++++++++ 6 files changed, 6171 insertions(+), 6145 deletions(-) create mode 100644 app/config/collections/bucket.php create mode 100644 app/config/collections/common.php create mode 100644 app/config/collections/database.php create mode 100644 app/config/collections/platform.php create mode 100644 app/config/collections/project.php diff --git a/app/config/collections.php b/app/config/collections.php index a55ab1abd0..fc8d613b6d 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1,12 +1,15 @@ <?php -use Appwrite\Auth\Auth; use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\Helpers\ID; -$providers = Config::getParam('oAuthProviders', []); +$common = include __DIR__ . '/collections/common.php'; +$bucket = include __DIR__ . '/collections/bucket.php'; +$project = include __DIR__ . '/collections/project.php'; +$database = include __DIR__ . '/collections/database.php'; +$platform = include __DIR__ . '/collections/platform.php'; + $auth = Config::getParam('auth', []); +$providers = Config::getParam('oAuthProviders', []); /** * $collection => id of the parent collection where this will be inserted @@ -17,6148 +20,11 @@ $auth = Config::getParam('auth', []); * indexes => list of indexes */ -$commonCollections = [ - 'cache' => [ - '$collection' => Database::METADATA, - '$id' => 'cache', - 'name' => 'Cache', - 'attributes' => [ - [ - '$id' => 'resource', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => 'signature', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_resource', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resource'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'users' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('users'), - 'name' => 'Users', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('email'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 320, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('phone'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, // leading '+' and 15 digitts maximum by E.164 format - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('labels'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('passwordHistory'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('password'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => 'hash', // Hashing algorithm used to hash the password - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => Auth::DEFAULT_ALGO, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('hashOptions'), // Configuration of hashing algorithm - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => Auth::DEFAULT_ALGO_OPTIONS, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('passwordUpdate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('prefs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('registration'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('emailVerification'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('phoneVerification'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('reset'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mfa'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mfaRecoveryCodes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('authenticators'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryAuthenticators'], - ], - [ - '$id' => ID::custom('sessions'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQuerySessions'], - ], - [ - '$id' => ID::custom('tokens'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTokens'], - ], - [ - '$id' => ID::custom('challenges'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryChallenges'], - ], - [ - '$id' => ID::custom('memberships'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryMemberships'], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTargets'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['userSearch'], - ], - [ - '$id' => ID::custom('accessedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_email'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['email'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_phone'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['phone'], - 'lengths' => [16], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_status'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_passwordUpdate'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['passwordUpdate'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_registration'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['registration'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_emailVerification'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['emailVerification'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_phoneVerification'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['phoneVerification'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'tokens' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('tokens'), - 'name' => 'Tokens', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('userAgent'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('ip'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 45, // https://stackoverflow.com/a/166157/2299554 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'authenticators' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('authenticators'), - 'name' => 'Authenticators', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('verified'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'challenges' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('challenges'), - 'name' => 'Challenges', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('token'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], [ - '$id' => ID::custom('code'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'sessions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('sessions'), - 'name' => 'Sessions', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerUid'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerAccessToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('providerAccessTokenExpiry'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('providerRefreshToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('userAgent'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('ip'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 45, // https://stackoverflow.com/a/166157/2299554 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('countryCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientEngine'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientEngineVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceBrand'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceModel'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('factors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('mfaUpdatedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_provider_providerUid'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider', 'providerUid'], - 'lengths' => [128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'identities' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('identities'), - 'name' => 'Identities', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerUid'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerEmail'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 320, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerAccessToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('providerAccessTokenExpiry'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('providerRefreshToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - // Used to store data from provider that may or may not be sensitive - '$id' => ID::custom('secrets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userInternalId_provider_providerUid'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['userInternalId', 'provider', 'providerUid'], - 'lengths' => [11, 128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_provider_providerUid'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['provider', 'providerUid'], - 'lengths' => [128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_provider'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerUid'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerUid'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerEmail'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerEmail'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerAccessTokenExpiry'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerAccessTokenExpiry'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'teams' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('teams'), - 'name' => 'Teams', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('total'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('prefs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_total'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['total'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'memberships' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('memberships'), - 'name' => 'Memberships', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('roles'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('invited'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('joined'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('confirm'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_unique'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['teamInternalId', 'userInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_team'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_teamId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_invited'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['invited'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_joined'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['joined'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_confirm'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['confirm'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'buckets' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('buckets'), - 'name' => 'Buckets', - 'attributes' => [ - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 128, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('fileSecurity'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 1, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('maximumFileSize'), - 'type' => Database::VAR_INTEGER, - 'signed' => false, - 'size' => 8, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('allowedFileExtensions'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 64, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => true, - ], - [ - '$id' => 'compression', - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 10, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('encryption'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('antivirus'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_fileSecurity'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['fileSecurity'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_maximumFileSize'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['maximumFileSize'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_encryption'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['encryption'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_antivirus'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['antivirus'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ] - ], - - 'stats' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('stats'), - 'name' => 'Stats', - 'attributes' => [ - [ - '$id' => ID::custom('metric'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('value'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('time'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('period'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_time'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['time'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - [ - '$id' => ID::custom('_key_period_time'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['period', 'time'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_metric_period_time'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['metric', 'period', 'time'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - ], - ], - - 'providers' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('providers'), - 'name' => 'Providers', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('credentials'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('options'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['providerSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_provider'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['type'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled', 'type'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], - - 'messages' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('messages'), - 'name' => 'Messages', - 'attributes' => [ - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => 'processing', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('topics'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('users'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduledAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deliveredAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('deliveryErrors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('deliveredTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['messageSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'topics' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('topics'), - 'name' => 'Topics', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('subscribe'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('emailTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('smsTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pushTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTopicTargets'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['topicSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'subscribers' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('subscribers'), - 'name' => 'Subscribers', - 'attributes' => [ - [ - '$id' => ID::custom('targetId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('targetInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('topicId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('topicInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_targetId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['targetId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_targetInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['targetInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_topicId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['topicId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_topicInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['topicInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_unique_target_topic'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['targetInternalId', 'topicInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'targets' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('targets'), - 'name' => 'Targets', - 'attributes' => [ - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sessionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sessionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('identifier'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('expired'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_providerInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_identifier'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['identifier'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], -]; - -$projectCollections = array_merge([ - 'databases' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('databases'), - 'name' => 'Databases', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'size' => 256, - 'required' => true, - 'signed' => true, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('originalId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => null, - 'array' => false, - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'attributes' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('attributes'), - 'name' => 'Attributes', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('error'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('required'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('default'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['casting'], - ], - [ - '$id' => ID::custom('signed'), - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('array'), - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('format'), - 'type' => Database::VAR_STRING, - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('formatOptions'), - 'type' => Database::VAR_STRING, - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => new stdClass(), - 'array' => false, - 'filters' => ['json', 'range', 'enum'], - ], - [ - '$id' => ID::custom('filters'), - 'type' => Database::VAR_STRING, - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('options'), - 'type' => Database::VAR_STRING, - 'size' => 16384, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_db_collection'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['databaseInternalId', 'collectionInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - ], - ], - - 'indexes' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('indexes'), - 'name' => 'Indexes', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('error'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('attributes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('lengths'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('orders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_db_collection'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['databaseInternalId', 'collectionInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - ], - ], - - 'functions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('functions'), - 'name' => 'Functions', - 'attributes' => [ - [ - '$id' => ID::custom('execute'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('live'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRootDirectory'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerSilentMode'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('logging'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('runtime'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deployment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('vars'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryVariables'], - ], - [ - '$id' => ID::custom('varsProject'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryProjectVariables'], - ], - [ - '$id' => ID::custom('events'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('schedule'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('timeout'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('version'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8, - 'signed' => true, - 'required' => false, - 'default' => 'v4', - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('entrypoint'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('commands'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('specification'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => false, - 'required' => false, - 'default' => APP_FUNCTION_SPECIFICATION_DEFAULT, - 'filters' => [], - ], - [ - '$id' => ID::custom('scopes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_repositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['repositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_repositoryInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['repositoryInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_runtime'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['runtime'], - 'lengths' => [64], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deployment'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'deployments' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('deployments'), - 'name' => 'Deployments', - 'attributes' => [ - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('buildInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('buildId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('entrypoint'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('commands'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryName'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryOwner'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitHash'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitAuthorUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitAuthor'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitMessage'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerBranchUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRootDirectory'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommentId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 2048, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('metadata'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('chunksTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksUploaded'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('activate'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_resource'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resource_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_size'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['size'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_buildId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['buildId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_activate'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['activate'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'builds' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('builds'), - 'name' => 'Builds', - 'attributes' => [ - [ - '$id' => ID::custom('startTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('endTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('runtime'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => 'processing', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => 'local', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('source'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deploymentId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'executions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('executions'), - 'name' => 'Executions', - 'attributes' => [ - [ - '$id' => ID::custom('functionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('functionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('trigger'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_FLOAT, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('errors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('requestMethod'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('requestPath'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('requestHeaders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('responseStatusCode'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('responseHeaders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduledAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_function'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['functionId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_trigger'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['trigger'], - 'lengths' => [32], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_status'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [32], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_requestMethod'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['requestMethod'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_requestPath'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['requestPath'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deploymentId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_responseStatusCode'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['responseStatusCode'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_duration'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['duration'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'variables' => [ - '$collection' => Database::METADATA, - '$id' => 'variables', - 'name' => 'variables', - 'attributes' => [ - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'key', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'value', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8192, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'] - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [], - ], - [ - '$id' => '_key_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceId_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId', 'resourceType'], - 'lengths' => [Database::LENGTH_KEY, 100], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => '_key_uniqueKey', - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['resourceId', 'key', 'resourceType'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY, 100], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => '_key_key', - 'type' => Database::INDEX_KEY, - 'attributes' => ['key'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'migrations' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('migrations'), - 'name' => 'Migrations', - 'attributes' => [ - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('stage'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('source'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8192, // reduce size - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('destination'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, // make true after patch script - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('credentials'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65536, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('resources'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('statusCounters'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 3000, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('resourceData'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 131070, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('errors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => '_key_status', - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_stage', - 'type' => Database::INDEX_KEY, - 'attributes' => ['stage'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_source', - 'type' => Database::INDEX_KEY, - 'attributes' => ['source'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], -], $commonCollections); - -$consoleCollections = array_merge([ - 'projects' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('projects'), - 'name' => 'Projects', - 'attributes' => [ - [ - '$id' => ID::custom('teamInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('description'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('database'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logo'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('url'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('version'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalCountry'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalState'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalCity'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalAddress'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalTaxId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('services'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('apis'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('smtp'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('templates'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, // TODO make sure size fits - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('auths'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('oAuthProviders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('platforms'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryPlatforms'], - ], - [ - '$id' => ID::custom('webhooks'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryWebhooks'], - ], - [ - '$id' => ID::custom('keys'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryKeys'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pingCount'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pingedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_team'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_pingCount'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['pingCount'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_pingedAt'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['pingedAt'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], - - 'schedules' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('schedules'), - 'name' => 'schedules', - 'attributes' => [ - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceUpdatedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('schedule'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('active'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 10, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_region_resourceType_projectId_resourceId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType', 'projectId', 'resourceId'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'platforms' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('platforms'), - 'name' => 'platforms', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('store'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('hostname'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'keys' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('keys'), - 'name' => 'keys', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scopes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // var_dump of \bin2hex(\random_bytes(128)) => string(256) doubling for encryption - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('accessedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('sdks'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'webhooks' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('webhooks'), - 'name' => 'webhooks', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('url'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('httpUser'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('httpPass'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, // TODO will the length suffice after encryption? - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('security'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('events'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('signatureKey'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('attempts'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'certificates' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('certificates'), - 'name' => 'Certificates', - 'attributes' => [ - [ - '$id' => ID::custom('domain'), - 'type' => Database::VAR_STRING, - 'format' => '', - // The maximum total length of a domain name or number is 255 characters. - // https://datatracker.ietf.org/doc/html/rfc2821#section-4.5.3.1 - // https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.2 - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('issueDate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('renewDate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('attempts'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('updated'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_domain'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['domain'], - 'lengths' => [255], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'realtime' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('realtime'), - 'name' => 'Realtime Connections', - 'attributes' => [ - [ - '$id' => ID::custom('container'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('timestamp'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('value'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], //TODO: use json filter - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_timestamp'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['timestamp'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - ] - ], - - 'rules' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('rules'), - 'name' => 'Rules', - 'attributes' => [ - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('domain'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('certificateId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_domain'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['domain'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'installations' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('installations'), - 'name' => 'installations', - 'attributes' => [ - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerInstallationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('organization'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('personal'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - ], - 'indexes' => [ - - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerInstallationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerInstallationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'repositories' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('repositories'), - 'name' => 'repositories', - 'attributes' => [ - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerPullRequestIds'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resourceId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resourceType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'vcsComments' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcsComments'), - 'name' => 'vcsComments', - 'attributes' => [ - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerCommentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerPullRequestId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerPullRequestId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerPullRequestId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerBranch'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerBranch'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'vcsCommentLocks' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcsCommentLocks'), - 'name' => 'vcsCommentLocks', - 'attributes' => [], - 'indexes' => [] - ], -], $commonCollections); - -$bucketCollections = [ - 'files' => [ - '$collection' => ID::custom('buckets'), - '$id' => ID::custom('files'), - '$name' => 'Files', - 'attributes' => [ - [ - 'array' => false, - '$id' => ID::custom('bucketId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('bucketInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('signature'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('metadata'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('sizeOriginal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sizeActual'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('algorithm'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('comment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLCipher'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLTag'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLIV'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksUploaded'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_bucket'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['bucketId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_signature'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['signature'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_mimeType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['mimeType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_sizeOriginal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['sizeOriginal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksTotal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksTotal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksUploaded'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksUploaded'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ] - ], -]; - -$dbCollections = [ - 'collections' => [ - '$collection' => ID::custom('databases'), - '$id' => ID::custom('collections'), - 'name' => 'Collections', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'size' => 256, - 'required' => true, - 'signed' => true, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('documentSecurity'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('attributes'), - 'type' => Database::VAR_STRING, - 'size' => 1000000, - 'required' => false, - 'signed' => true, - 'array' => false, - 'filters' => ['subQueryAttributes'], - ], - [ - '$id' => ID::custom('indexes'), - 'type' => Database::VAR_STRING, - 'size' => 1000000, - 'required' => false, - 'signed' => true, - 'array' => false, - 'filters' => ['subQueryIndexes'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_documentSecurity'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['documentSecurity'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ] -]; - - $collections = [ - 'projects' => $projectCollections, - 'console' => $consoleCollections, - 'buckets' => $bucketCollections, - 'databases' => $dbCollections + 'buckets' => $bucket, + 'databases' => $database, + 'projects' => array_merge($project, $common), + 'console' => array_merge($platform, $common), ]; return $collections; diff --git a/app/config/collections/bucket.php b/app/config/collections/bucket.php new file mode 100644 index 0000000000..289e351f35 --- /dev/null +++ b/app/config/collections/bucket.php @@ -0,0 +1,270 @@ +<?php + +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; + +return [ + 'files' => [ + '$collection' => ID::custom('buckets'), + '$id' => ID::custom('files'), + '$name' => 'Files', + 'attributes' => [ + [ + 'array' => false, + '$id' => ID::custom('bucketId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('bucketInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('path'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('signature'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('metadata'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('sizeOriginal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sizeActual'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('algorithm'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('comment'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLCipher'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLTag'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLIV'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksUploaded'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_bucket'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['bucketId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_signature'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['signature'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_mimeType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['mimeType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_sizeOriginal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['sizeOriginal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksTotal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksTotal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksUploaded'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksUploaded'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ] + ], +]; diff --git a/app/config/collections/common.php b/app/config/collections/common.php new file mode 100644 index 0000000000..1280595221 --- /dev/null +++ b/app/config/collections/common.php @@ -0,0 +1,2357 @@ +<?php + +use Appwrite\Auth\Auth; +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; + +return [ + 'cache' => [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'users' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('users'), + 'name' => 'Users', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('email'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 320, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('phone'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, // leading '+' and 15 digitts maximum by E.164 format + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('labels'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('passwordHistory'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('password'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => 'hash', // Hashing algorithm used to hash the password + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => Auth::DEFAULT_ALGO, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('hashOptions'), // Configuration of hashing algorithm + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => Auth::DEFAULT_ALGO_OPTIONS, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('passwordUpdate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('prefs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('registration'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('emailVerification'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('phoneVerification'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('reset'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mfa'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mfaRecoveryCodes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('authenticators'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryAuthenticators'], + ], + [ + '$id' => ID::custom('sessions'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQuerySessions'], + ], + [ + '$id' => ID::custom('tokens'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTokens'], + ], + [ + '$id' => ID::custom('challenges'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryChallenges'], + ], + [ + '$id' => ID::custom('memberships'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryMemberships'], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTargets'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['userSearch'], + ], + [ + '$id' => ID::custom('accessedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_email'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['email'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_phone'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['phone'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_passwordUpdate'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['passwordUpdate'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_registration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['registration'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_emailVerification'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['emailVerification'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_phoneVerification'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['phoneVerification'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'tokens' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('tokens'), + 'name' => 'Tokens', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('userAgent'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('ip'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 45, // https://stackoverflow.com/a/166157/2299554 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'authenticators' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('authenticators'), + 'name' => 'Authenticators', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('verified'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'challenges' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('challenges'), + 'name' => 'Challenges', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('token'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], [ + '$id' => ID::custom('code'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'sessions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('sessions'), + 'name' => 'Sessions', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerUid'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('providerAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('providerRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('userAgent'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('ip'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 45, // https://stackoverflow.com/a/166157/2299554 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('countryCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientEngine'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientEngineVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceBrand'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceModel'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('factors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('mfaUpdatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_provider_providerUid'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider', 'providerUid'], + 'lengths' => [128, 128], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'identities' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('identities'), + 'name' => 'Identities', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerUid'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerEmail'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 320, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('providerAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('providerRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + // Used to store data from provider that may or may not be sensitive + '$id' => ID::custom('secrets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userInternalId_provider_providerUid'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['userInternalId', 'provider', 'providerUid'], + 'lengths' => [11, 128, 128], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_provider_providerUid'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['provider', 'providerUid'], + 'lengths' => [128, 128], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_provider'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerUid'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerUid'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerEmail'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerEmail'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerAccessTokenExpiry'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerAccessTokenExpiry'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'teams' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('teams'), + 'name' => 'Teams', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('total'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('prefs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_total'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['total'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'memberships' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('memberships'), + 'name' => 'Memberships', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('roles'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('invited'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('joined'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('confirm'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_unique'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['teamInternalId', 'userInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_team'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_teamId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_invited'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['invited'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_joined'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['joined'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_confirm'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['confirm'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'buckets' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('buckets'), + 'name' => 'Buckets', + 'attributes' => [ + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 128, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('fileSecurity'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 1, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('maximumFileSize'), + 'type' => Database::VAR_INTEGER, + 'signed' => false, + 'size' => 8, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('allowedFileExtensions'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 64, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => true, + ], + [ + '$id' => 'compression', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 10, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('encryption'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('antivirus'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_fileSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['fileSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_maximumFileSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['maximumFileSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_encryption'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['encryption'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_antivirus'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['antivirus'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ] + ], + + 'stats' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('stats'), + 'name' => 'Stats', + 'attributes' => [ + [ + '$id' => ID::custom('metric'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('time'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('period'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + [ + '$id' => ID::custom('_key_period_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_metric_period_time'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['metric', 'period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ], + ], + + 'providers' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('providers'), + 'name' => 'Providers', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('credentials'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['providerSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_provider'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['type'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled', 'type'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], + + 'messages' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('messages'), + 'name' => 'Messages', + 'attributes' => [ + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => 'processing', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('topics'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('users'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduledAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deliveredAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('deliveryErrors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('deliveredTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['messageSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'topics' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('topics'), + 'name' => 'Topics', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('subscribe'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('emailTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('smsTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pushTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTopicTargets'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['topicSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'subscribers' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('subscribers'), + 'name' => 'Subscribers', + 'attributes' => [ + [ + '$id' => ID::custom('targetId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('targetInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('topicId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('topicInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_targetId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['targetId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_targetInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['targetInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_topicId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['topicId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_topicInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['topicInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_unique_target_topic'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['targetInternalId', 'topicInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'targets' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('targets'), + 'name' => 'Targets', + 'attributes' => [ + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sessionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sessionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('identifier'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('expired'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_providerInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_identifier'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['identifier'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], +]; diff --git a/app/config/collections/database.php b/app/config/collections/database.php new file mode 100644 index 0000000000..995caecb7f --- /dev/null +++ b/app/config/collections/database.php @@ -0,0 +1,126 @@ +<?php + +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; + +return [ + 'collections' => [ + '$collection' => ID::custom('databases'), + '$id' => ID::custom('collections'), + 'name' => 'Collections', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'size' => 256, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('documentSecurity'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('attributes'), + 'type' => Database::VAR_STRING, + 'size' => 1000000, + 'required' => false, + 'signed' => true, + 'array' => false, + 'filters' => ['subQueryAttributes'], + ], + [ + '$id' => ID::custom('indexes'), + 'type' => Database::VAR_STRING, + 'size' => 1000000, + 'required' => false, + 'signed' => true, + 'array' => false, + 'filters' => ['subQueryIndexes'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_documentSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['documentSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ] +]; diff --git a/app/config/collections/platform.php b/app/config/collections/platform.php new file mode 100644 index 0000000000..a5fedb6461 --- /dev/null +++ b/app/config/collections/platform.php @@ -0,0 +1,1534 @@ +<?php + +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; + +$providers = Config::getParam('oAuthProviders', []); + +return [ + 'projects' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('projects'), + 'name' => 'Projects', + 'attributes' => [ + [ + '$id' => ID::custom('teamInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('description'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('database'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logo'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('url'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('version'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalCountry'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalState'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalCity'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalAddress'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalTaxId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('services'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('apis'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('smtp'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('templates'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, // TODO make sure size fits + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('auths'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('oAuthProviders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('platforms'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryPlatforms'], + ], + [ + '$id' => ID::custom('webhooks'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryWebhooks'], + ], + [ + '$id' => ID::custom('keys'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryKeys'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pingCount'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pingedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_team'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_pingCount'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['pingCount'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_pingedAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['pingedAt'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], + + 'schedules' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('schedules'), + 'name' => 'schedules', + 'attributes' => [ + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceUpdatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('schedule'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('active'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 10, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_region_resourceType_projectId_resourceId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['region', 'resourceType', 'projectId', 'resourceId'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'platforms' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('platforms'), + 'name' => 'platforms', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('store'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('hostname'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'keys' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('keys'), + 'name' => 'keys', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scopes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // var_dump of \bin2hex(\random_bytes(128)) => string(256) doubling for encryption + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('accessedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('sdks'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'webhooks' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('webhooks'), + 'name' => 'webhooks', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('url'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('httpUser'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('httpPass'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, // TODO will the length suffice after encryption? + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('security'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('events'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('signatureKey'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('attempts'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'certificates' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('certificates'), + 'name' => 'Certificates', + 'attributes' => [ + [ + '$id' => ID::custom('domain'), + 'type' => Database::VAR_STRING, + 'format' => '', + // The maximum total length of a domain name or number is 255 characters. + // https://datatracker.ietf.org/doc/html/rfc2821#section-4.5.3.1 + // https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.2 + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('issueDate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('renewDate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('attempts'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('updated'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_domain'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['domain'], + 'lengths' => [255], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'realtime' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('realtime'), + 'name' => 'Realtime Connections', + 'attributes' => [ + [ + '$id' => ID::custom('container'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('timestamp'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], //TODO: use json filter + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_timestamp'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['timestamp'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ] + ], + + 'rules' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('rules'), + 'name' => 'Rules', + 'attributes' => [ + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('domain'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('certificateId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_domain'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['domain'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'installations' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('installations'), + 'name' => 'installations', + 'attributes' => [ + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerInstallationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('organization'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('personal'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + ], + 'indexes' => [ + + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerInstallationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerInstallationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'repositories' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('repositories'), + 'name' => 'repositories', + 'attributes' => [ + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerPullRequestIds'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resourceId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resourceType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'vcsComments' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('vcsComments'), + 'name' => 'vcsComments', + 'attributes' => [ + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerCommentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerPullRequestId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerPullRequestId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerPullRequestId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerBranch'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerBranch'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'vcsCommentLocks' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('vcsCommentLocks'), + 'name' => 'vcsCommentLocks', + 'attributes' => [], + 'indexes' => [] + ] +]; diff --git a/app/config/collections/project.php b/app/config/collections/project.php new file mode 100644 index 0000000000..e77751c124 --- /dev/null +++ b/app/config/collections/project.php @@ -0,0 +1,1873 @@ +<?php + +use Utopia\Database\Database; +use Utopia\Database\Helpers\ID; + +return [ + 'databases' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('databases'), + 'name' => 'Databases', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'size' => 256, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('originalId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => null, + 'array' => false, + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'attributes' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('attributes'), + 'name' => 'Attributes', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('error'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('size'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('required'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('default'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['casting'], + ], + [ + '$id' => ID::custom('signed'), + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('array'), + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('format'), + 'type' => Database::VAR_STRING, + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('formatOptions'), + 'type' => Database::VAR_STRING, + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => new stdClass(), + 'array' => false, + 'filters' => ['json', 'range', 'enum'], + ], + [ + '$id' => ID::custom('filters'), + 'type' => Database::VAR_STRING, + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'size' => 16384, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_db_collection'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['databaseInternalId', 'collectionInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + ], + ], + + 'indexes' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('indexes'), + 'name' => 'Indexes', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('error'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('attributes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('lengths'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('orders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_db_collection'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['databaseInternalId', 'collectionInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + ], + ], + + 'functions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('functions'), + 'name' => 'Functions', + 'attributes' => [ + [ + '$id' => ID::custom('execute'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('live'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRootDirectory'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerSilentMode'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('logging'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('runtime'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deployment'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('vars'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryVariables'], + ], + [ + '$id' => ID::custom('varsProject'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryProjectVariables'], + ], + [ + '$id' => ID::custom('events'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('schedule'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('timeout'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('version'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8, + 'signed' => true, + 'required' => false, + 'default' => 'v4', + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('entrypoint'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('commands'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('specification'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => false, + 'required' => false, + 'default' => APP_FUNCTION_SPECIFICATION_DEFAULT, + 'filters' => [], + ], + [ + '$id' => ID::custom('scopes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_runtime'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['runtime'], + 'lengths' => [64], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deployment'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deployment'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'deployments' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('deployments'), + 'name' => 'Deployments', + 'attributes' => [ + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('entrypoint'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('commands'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('path'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryName'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryOwner'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitHash'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitAuthorUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitAuthor'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitMessage'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerBranchUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRootDirectory'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommentId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 2048, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('size'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('metadata'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('chunksTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksUploaded'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('activate'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_resource'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resource_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_size'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['size'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_buildId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['buildId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_activate'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['activate'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'builds' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('builds'), + 'name' => 'Builds', + 'attributes' => [ + [ + '$id' => ID::custom('startTime'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('endTime'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('duration'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('size'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('runtime'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => true, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => 'processing', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('path'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => true, + 'default' => 'local', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('source'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => true, + 'default' => '', + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_deployment'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'executions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('executions'), + 'name' => 'Executions', + 'attributes' => [ + [ + '$id' => ID::custom('functionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('functionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('trigger'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('duration'), + 'type' => Database::VAR_FLOAT, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('errors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('requestMethod'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('requestPath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('requestHeaders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('responseStatusCode'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('responseHeaders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduledAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_function'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['functionId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_trigger'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['trigger'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_requestMethod'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['requestMethod'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_requestPath'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['requestPath'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deployment'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_responseStatusCode'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['responseStatusCode'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_duration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['duration'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'variables' => [ + '$collection' => Database::METADATA, + '$id' => 'variables', + 'name' => 'variables', + 'attributes' => [ + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'value', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8192, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'] + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_resourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [], + ], + [ + '$id' => '_key_resourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceId_resourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId', 'resourceType'], + 'lengths' => [Database::LENGTH_KEY, 100], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => '_key_uniqueKey', + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['resourceId', 'key', 'resourceType'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY, 100], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => '_key_key', + 'type' => Database::INDEX_KEY, + 'attributes' => ['key'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'migrations' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('migrations'), + 'name' => 'Migrations', + 'attributes' => [ + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('stage'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('source'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8192, // reduce size + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('destination'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, // make true after patch script + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('credentials'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65536, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('resources'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('statusCounters'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 3000, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('resourceData'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 131070, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('errors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => '_key_status', + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_stage', + 'type' => Database::INDEX_KEY, + 'attributes' => ['stage'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_source', + 'type' => Database::INDEX_KEY, + 'attributes' => ['source'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], +]; From 0f2985cec1a2e80fc325b59824eedad64519b5f2 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 09:19:09 +0200 Subject: [PATCH 189/340] database crud usage addition --- app/controllers/api/databases.php | 56 +++++++++++++++---------------- app/init.php | 4 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4275ab52ae..e51201a467 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2886,7 +2886,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $database = Authorization::skip(function () use ($queueForUsage, $dbForProject, $databaseId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('databases', $databaseId); }); @@ -2899,7 +2899,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId){ - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); }); @@ -2989,7 +2989,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($relatedCollectionId, $dbForProject, $queueForUsage) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); } ); @@ -3005,7 +3005,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } if ($relation instanceof Document) { $current = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); } ); @@ -3039,7 +3039,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); - $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); } catch (StructureException $e) { throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (DuplicateException $e) { @@ -3070,7 +3070,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); } ); @@ -3133,7 +3133,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('queueForUsage') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3143,7 +3143,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3174,7 +3174,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); $cursorDocument = Authorization::skip(function() use ($dbForProject, $queueForUsage, $collection, $database, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); }); @@ -3186,10 +3186,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); // Add $collectionId and $databaseId for all documents $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage): bool { @@ -3220,7 +3220,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function() use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); }); @@ -3305,7 +3305,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3315,7 +3315,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); }); @@ -3326,7 +3326,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen try { $queries = Query::parseQueries($queries); $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { @@ -3363,7 +3363,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); } ); @@ -3527,7 +3527,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $database = Authorization::skip(function () use($queueForUsage, $dbForProject, $databaseId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('databases', $databaseId); }); @@ -3539,7 +3539,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); }); @@ -3550,7 +3550,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Read permission should not be required for update /** @var Document $document */ $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); }); @@ -3617,7 +3617,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); }); @@ -3633,7 +3633,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } if ($relation instanceof Document) { $oldDocument = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); }); @@ -3663,7 +3663,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum try { $document = $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $document, $newDocument) { - $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); return $dbForProject->updateDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document->getId(), $newDocument); }); } catch (AuthorizationException) { @@ -3698,7 +3698,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); }); @@ -3762,7 +3762,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3772,7 +3772,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu } $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); }); @@ -3782,7 +3782,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu // Read permission should not be required for delete $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); }); @@ -3792,7 +3792,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu try { $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_WRITE, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); $dbForProject->deleteDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); }); } catch (NotFoundException $e) { @@ -3821,7 +3821,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_API_READ, 1); + $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); }); diff --git a/app/init.php b/app/init.php index d5b8e4b235..d942e056db 100644 --- a/app/init.php +++ b/app/init.php @@ -232,8 +232,8 @@ const API_KEY_DYNAMIC = 'dynamic'; // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; -const METRIC_DATABASE_API_READ = 'database.api.events.read'; -const METRIC_DATABASE_API_WRITE = 'database.api.events.write'; +const METRIC_DATABASE_OPERATIONS_READS = 'databases.operations.reads'; +const METRIC_DATABASE_OPERATIONS_WRITES = 'databases.operations.writes'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; From 42589de95ef41114d247fdbceacce8ea3d708233 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 09:56:14 +0200 Subject: [PATCH 190/340] database crud usage addition --- app/controllers/api/databases.php | 170 +++++++++++++----------------- app/init.php | 2 + 2 files changed, 75 insertions(+), 97 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index e51201a467..ea17065d45 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2885,11 +2885,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); } - $database = Authorization::skip(function () use ($queueForUsage, $dbForProject, $databaseId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('databases', $databaseId); - }); - + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -2898,10 +2894,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId){ - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - }); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2988,10 +2981,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($relatedCollectionId, $dbForProject, $queueForUsage) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - } + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3004,10 +2995,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relation = new Document($relation); } if ($relation instanceof Document) { - $current = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); - } + $current = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -3039,7 +3028,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); } catch (StructureException $e) { throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (DuplicateException $e) { @@ -3049,7 +3037,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3069,10 +3057,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - } + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3107,6 +3093,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection }); @@ -3133,7 +3121,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('queueForUsage') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3143,7 +3130,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3173,10 +3159,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(function() use ($dbForProject, $queueForUsage, $collection, $database, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); - }); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -3186,13 +3169,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage): bool { + $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { if ($document->isEmpty()) { return false; } @@ -3219,10 +3199,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function() use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - }); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -3273,6 +3250,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } } + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), 1) + ; + $response->dynamic(new Document([ 'total' => $total, 'documents' => $documents, @@ -3305,7 +3287,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3314,10 +3295,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - }); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3326,7 +3304,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen try { $queries = Query::parseQueries($queries); $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { @@ -3338,7 +3315,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { if ($document->isEmpty()) { return; } @@ -3362,10 +3339,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - } + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3378,6 +3353,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $processDocument($collection, $document); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), 1) + ; + $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3526,10 +3506,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); } - $database = Authorization::skip(function () use($queueForUsage, $dbForProject, $databaseId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('databases', $databaseId); - }); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3538,10 +3515,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - }); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3549,10 +3523,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); - }); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -3594,7 +3565,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, $queueForUsage) { + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { $relationships = \array_filter( $collection->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP @@ -3616,10 +3587,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - }); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); foreach ($relations as &$relation) { // If the relation is an array it can be either update or create a child document. @@ -3632,15 +3602,17 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relation = new Document($relation); } if ($relation instanceof Document) { - $oldDocument = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollection, $relation) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()); - }); - + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $relation->getId() + )); $relation->removeAttribute('$collectionId'); $relation->removeAttribute('$databaseId'); // Attribute $collection is required for Utopia. - $relation->setAttribute('$collection', 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $relation->setAttribute( + '$collection', + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + ); if ($oldDocument->isEmpty()) { if (isset($relation['$id']) && $relation['$id'] === 'unique()') { @@ -3662,10 +3634,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection($collection, $newDocument); try { - $document = $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $document, $newDocument) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); - return $dbForProject->updateDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document->getId(), $newDocument); - }); + $document = $dbForProject->withRequestTimestamp( + $requestTimestamp, + fn () => $dbForProject->updateDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $document->getId(), + $newDocument + ) + ); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (DuplicateException) { @@ -3677,7 +3653,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3697,10 +3673,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - }); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); foreach ($related as $relation) { if ($relation instanceof Document) { @@ -3712,6 +3687,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $processDocument($collection, $document); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ; + $response->dynamic($document, Response::MODEL_DOCUMENT); $relationships = \array_map( @@ -3762,7 +3742,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('mode') ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3771,36 +3750,32 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - }); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); - }); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($queueForUsage, $dbForProject, $database, $collection, $documentId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_WRITES, 1); - $dbForProject->deleteDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + $dbForProject->deleteDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $documentId + ); }); } catch (NotFoundException $e) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $queueForUsage) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3820,10 +3795,9 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip(function () use ($queueForUsage, $dbForProject, $database, $relatedCollectionId) { - $queueForUsage->addMetric(METRIC_DATABASE_OPERATIONS_READS, 1); - return $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - }); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); foreach ($related as $relation) { if ($relation instanceof Document) { @@ -3852,6 +3826,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection $response->noContent(); diff --git a/app/init.php b/app/init.php index d942e056db..cf41bc8049 100644 --- a/app/init.php +++ b/app/init.php @@ -233,7 +233,9 @@ const API_KEY_DYNAMIC = 'dynamic'; const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; const METRIC_DATABASE_OPERATIONS_READS = 'databases.operations.reads'; +const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads'; const METRIC_DATABASE_OPERATIONS_WRITES = 'databases.operations.writes'; +const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; From c7841bb36ef0b503a6d1001ecfc78ca8ea360e44 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 09:59:59 +0200 Subject: [PATCH 191/340] database crud usage addition --- app/controllers/api/databases.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index ea17065d45..0ab84bf0fc 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3121,7 +3121,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('queueForUsage') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3285,9 +3284,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->inject('mode') ->inject('queueForUsage') ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); From fbbc9312eaf3ce85042efd74eb09f3e708394d7f Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 10:09:44 +0200 Subject: [PATCH 192/340] database crud usage addition --- app/controllers/api/databases.php | 61 +++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 0ab84bf0fc..1249ccb2fa 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3036,8 +3036,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $operations = 1; + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3049,6 +3051,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + if (empty($related)) { continue; } @@ -3093,8 +3099,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection }); @@ -3170,8 +3176,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $operations = 1; + // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { + $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { if ($document->isEmpty()) { return false; } @@ -3188,6 +3196,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + if (empty($related)) { continue; } @@ -3198,6 +3210,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + // todo: Use local cache for this getDocument $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); foreach ($relations as $index => $doc) { @@ -3250,8 +3263,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; $response->dynamic(new Document([ @@ -3311,8 +3324,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DOCUMENT_NOT_FOUND); } + $operations = 1; + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { if ($document->isEmpty()) { return; } @@ -3328,6 +3343,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + if (empty($related)) { continue; } @@ -3351,8 +3370,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $processDocument($collection, $document); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; $response->dynamic($document, Response::MODEL_DOCUMENT); @@ -3649,8 +3668,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $operations = 1; + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3662,6 +3683,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + if (empty($related)) { continue; } @@ -3685,8 +3710,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $processDocument($collection, $document); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ; $response->dynamic($document, Response::MODEL_DOCUMENT); @@ -3771,8 +3796,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $operations = 1; + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3784,6 +3811,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + if (empty($related)) { continue; } @@ -3823,8 +3854,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection $response->noContent(); From c0d48efe18b7ea40f654a7303c7f2192a4e5bf60 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 10:29:55 +0200 Subject: [PATCH 193/340] composer --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 1249ccb2fa..a0fea5e293 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3265,7 +3265,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic(new Document([ 'total' => $total, @@ -3372,7 +3372,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic($document, Response::MODEL_DOCUMENT); }); From e7e095907cdf58a2a5627109f9b164e60a34e021 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 10:44:56 +0200 Subject: [PATCH 194/340] composer --- app/controllers/api/databases.php | 4 ++-- app/init.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index a0fea5e293..1249ccb2fa 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3265,7 +3265,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic(new Document([ 'total' => $total, @@ -3372,7 +3372,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic($document, Response::MODEL_DOCUMENT); }); diff --git a/app/init.php b/app/init.php index cf41bc8049..2f83e7c3b2 100644 --- a/app/init.php +++ b/app/init.php @@ -232,9 +232,9 @@ const API_KEY_DYNAMIC = 'dynamic'; // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; -const METRIC_DATABASE_OPERATIONS_READS = 'databases.operations.reads'; +const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads'; const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads'; -const METRIC_DATABASE_OPERATIONS_WRITES = 'databases.operations.writes'; +const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes'; const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; From 504b7276cb3fc0c94967fd177151a629e629b50b Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 11:02:53 +0200 Subject: [PATCH 195/340] composer --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 1249ccb2fa..a0fea5e293 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3265,7 +3265,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic(new Document([ 'total' => $total, @@ -3372,7 +3372,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; + ; $response->dynamic($document, Response::MODEL_DOCUMENT); }); From 63cf093020451c8fba1668443e4a5432621d2ebe Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 13:53:57 +0200 Subject: [PATCH 196/340] file transformations usage --- app/controllers/api/storage.php | 15 ++++++++++++++- app/init.php | 10 ++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 7d4361a192..97fb5cc711 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -6,6 +6,7 @@ use Appwrite\Auth\Auth; use Appwrite\ClamAV\Network; use Appwrite\Event\Delete; use Appwrite\Event\Event; +use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Database\Validator\CustomId; @@ -886,7 +887,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal) { + ->inject('queueForUsage') + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal, Usage $queueForUsage) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); @@ -1014,6 +1016,17 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; + foreach([$width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output] as $param){ + if(!empty($param)){ + $queueForUsage + ->addMetric(METRIC_FILES_TRANSFORMATIONS, 1) + ->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1) + ; + break; + } + } + + $response ->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days ->setContentType($contentType) diff --git a/app/init.php b/app/init.php index 2f83e7c3b2..5e25fa905f 100644 --- a/app/init.php +++ b/app/init.php @@ -232,10 +232,6 @@ const API_KEY_DYNAMIC = 'dynamic'; // Usage metrics const METRIC_TEAMS = 'teams'; const METRIC_USERS = 'users'; -const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads'; -const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads'; -const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes'; -const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes'; const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; @@ -263,9 +259,15 @@ const METRIC_DOCUMENTS = 'documents'; const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage'; +const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads'; +const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads'; +const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes'; +const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes'; const METRIC_BUCKETS = 'buckets'; const METRIC_FILES = 'files'; const METRIC_FILES_STORAGE = 'files.storage'; +const METRIC_FILES_TRANSFORMATIONS = 'files.transformations'; +const METRIC_BUCKET_ID_FILES_TRANSFORMATIONS = '{bucketInternalId}.files.transformations'; const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; const METRIC_FUNCTIONS = 'functions'; From 6b45293f7828f36ee590019a1593c84a6b175747 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 13:55:30 +0200 Subject: [PATCH 197/340] file transformations usage --- app/controllers/api/storage.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 97fb5cc711..8431fb19e3 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1016,14 +1016,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; - foreach([$width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output] as $param){ - if(!empty($param)){ - $queueForUsage - ->addMetric(METRIC_FILES_TRANSFORMATIONS, 1) - ->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1) - ; - break; - } + foreach ([$width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output] as $parameter) { + if (!empty($parameter)) { + $queueForUsage + ->addMetric(METRIC_FILES_TRANSFORMATIONS, 1) + ->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1) + ; + break; + } } From bdb93cd3234a7507e365af2f95210715b752fe84 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 2 Jan 2025 19:03:28 +0530 Subject: [PATCH 198/340] Update general.php --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index bb60b01ddd..db9df71341 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -835,7 +835,7 @@ App::error() $adapter = new Sentry($projectId, $key, $host); $logger = new Logger($adapter); - $logger->setSample(0.04); + $logger->setSample(0.01); $publish = true; } else { throw new \Exception('Invalid experimental logging provider'); From e895fd6e0ca026bf5687cdb5c8b007ecdba75c01 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Thu, 2 Jan 2025 19:19:39 +0530 Subject: [PATCH 199/340] address comment, change var and file name. --- app/config/collections.php | 12 ++++++------ app/config/collections/{bucket.php => buckets.php} | 0 .../collections/{database.php => databases.php} | 0 app/config/collections/{project.php => projects.php} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename app/config/collections/{bucket.php => buckets.php} (100%) rename app/config/collections/{database.php => databases.php} (100%) rename app/config/collections/{project.php => projects.php} (100%) diff --git a/app/config/collections.php b/app/config/collections.php index fc8d613b6d..d490a1dc99 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3,9 +3,9 @@ use Utopia\Config\Config; $common = include __DIR__ . '/collections/common.php'; -$bucket = include __DIR__ . '/collections/bucket.php'; -$project = include __DIR__ . '/collections/project.php'; -$database = include __DIR__ . '/collections/database.php'; +$buckets = include __DIR__ . '/collections/buckets.php'; +$projects = include __DIR__ . '/collections/projects.php'; +$databases = include __DIR__ . '/collections/databases.php'; $platform = include __DIR__ . '/collections/platform.php'; $auth = Config::getParam('auth', []); @@ -21,9 +21,9 @@ $providers = Config::getParam('oAuthProviders', []); */ $collections = [ - 'buckets' => $bucket, - 'databases' => $database, - 'projects' => array_merge($project, $common), + 'buckets' => $buckets, + 'databases' => $databases, + 'projects' => array_merge($projects, $common), 'console' => array_merge($platform, $common), ]; diff --git a/app/config/collections/bucket.php b/app/config/collections/buckets.php similarity index 100% rename from app/config/collections/bucket.php rename to app/config/collections/buckets.php diff --git a/app/config/collections/database.php b/app/config/collections/databases.php similarity index 100% rename from app/config/collections/database.php rename to app/config/collections/databases.php diff --git a/app/config/collections/project.php b/app/config/collections/projects.php similarity index 100% rename from app/config/collections/project.php rename to app/config/collections/projects.php From c5a49cc5375ab4fdc512fe9207802bd6f4fe18df Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 16:45:21 +0200 Subject: [PATCH 200/340] added operations debug header --- app/controllers/api/databases.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index a0fea5e293..c3f74389cc 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3077,6 +3077,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + + + $response->addHeader('X-Debug-Operations', $operations); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($document, Response::MODEL_DOCUMENT); @@ -3098,10 +3105,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->setPayload($response->getPayload(), sensitive: $relationships); - $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) - ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection }); App::get('/v1/databases/:databaseId/collections/:collectionId/documents') @@ -3267,6 +3270,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; + $response->addHeader('X-Debug-Operations', $operations); $response->dynamic(new Document([ 'total' => $total, 'documents' => $documents, @@ -3374,6 +3378,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; + $response->addHeader('X-Debug-Operations', $operations); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3714,6 +3719,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ; + $response->addHeader('X-Debug-Operations', $operations); $response->dynamic($document, Response::MODEL_DOCUMENT); $relationships = \array_map( @@ -3858,6 +3864,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + $response->addHeader('X-Debug-Operations', $operations); $response->noContent(); }); From 4acc2736e40a21b1c6ecfb9e97b1298086888b25 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Thu, 2 Jan 2025 16:46:38 +0200 Subject: [PATCH 201/340] added operations debug header --- app/controllers/api/storage.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 8431fb19e3..e92b55f140 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1016,16 +1016,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; - foreach ([$width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output] as $parameter) { - if (!empty($parameter)) { - $queueForUsage - ->addMetric(METRIC_FILES_TRANSFORMATIONS, 1) - ->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1) - ; - break; - } - } - + $queueForUsage + ->addMetric(METRIC_FILES_TRANSFORMATIONS, 1) + ->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1) + ; $response ->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days From 06a5876f35e86b48b4883f26651b27069d6e51e4 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 2 Jan 2025 17:06:22 +0200 Subject: [PATCH 202/340] No throwing Exception --- src/Appwrite/Platform/Workers/Databases.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 9c11dd4090..74c1250505 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -284,8 +284,9 @@ class Databases extends Action $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } - throw $e; - + /** + * No throwing Exception + */ } catch (\Throwable $e) { Console::error($e->getMessage()); From bd083ac2805aeb66ee5b11c65cbdccd946edb829 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 2 Jan 2025 17:54:47 +0200 Subject: [PATCH 203/340] database 0.53.29 --- composer.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/composer.lock b/composer.lock index ce5f358619..dbe9e079b5 100644 --- a/composer.lock +++ b/composer.lock @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.1", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" + "reference": "339ba21476eb184290361542f732ad12c97591ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", + "reference": "339ba21476eb184290361542f732ad12c97591ec", "shasum": "" }, "require": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.1" + "source": "https://github.com/symfony/http-client/tree/v7.2.2" }, "funding": [ { @@ -2544,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2024-12-30T18:35:15+00:00" }, { "name": "symfony/http-client-contracts", @@ -5126,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": { @@ -5146,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" @@ -5188,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", @@ -7735,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": { @@ -7779,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": [ { @@ -7795,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", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From e8e39dbd568a202eb7305acc9364d761ae1d2c9b Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 2 Jan 2025 17:57:46 +0200 Subject: [PATCH 204/340] Revert lock --- composer.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/composer.lock b/composer.lock index dbe9e079b5..ce5f358619 100644 --- a/composer.lock +++ b/composer.lock @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.2", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "339ba21476eb184290361542f732ad12c97591ec" + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", - "reference": "339ba21476eb184290361542f732ad12c97591ec", + "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", "shasum": "" }, "require": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.2" + "source": "https://github.com/symfony/http-client/tree/v7.2.1" }, "funding": [ { @@ -2544,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2024-12-30T18:35:15+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/http-client-contracts", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.18.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", "shasum": "" }, "require": { @@ -5146,10 +5146,10 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.66.0", - "illuminate/view": "^10.48.25", - "larastan/larastan": "^2.9.12", - "laravel-zero/framework": "^10.48.25", + "friendsofphp/php-cs-fixer": "^3.65.0", + "illuminate/view": "^10.48.24", + "larastan/larastan": "^2.9.11", + "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.17.0", "pestphp/pest": "^2.36.0" @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2024-11-26T15:34:00+00:00" }, { "name": "matthiasmullie/minify", @@ -7735,16 +7735,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", + "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", "shasum": "" }, "require": { @@ -7779,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.2" + "source": "https://github.com/symfony/finder/tree/v7.2.0" }, "funding": [ { @@ -7795,7 +7795,7 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "symfony/options-resolver", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 0203b67b28653e924418b5951150a6c25267bf72 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Fri, 3 Jan 2025 10:54:56 +0530 Subject: [PATCH 205/340] add: logs init. --- app/init.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/init.php b/app/init.php index c6847610c2..af83368082 100644 --- a/app/init.php +++ b/app/init.php @@ -869,6 +869,12 @@ $register->set('pools', function () { 'multiple' => true, 'schemes' => ['mariadb', 'mysql'], ], + 'logs' => [ + 'type' => 'database', + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB), + 'multiple' => true, + 'schemes' => ['mariadb', 'mysql'], + ], 'queue' => [ 'type' => 'queue', 'dsns' => $fallbackForRedis, From 31f8950b45c5daa754aefb9416cc77e3b49e4329 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Fri, 3 Jan 2025 15:30:55 +0530 Subject: [PATCH 206/340] add: hostname to audits. --- app/controllers/shared/api.php | 1 + src/Appwrite/Event/Audit.php | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 012dd13c73..182151a6c3 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -506,6 +506,7 @@ App::init() ->setMode($mode) ->setUserAgent($request->getUserAgent('')) ->setIP($request->getIP()) + ->setHostname($request->getHostname()) ->setEvent($route->getLabel('audits.event', '')) ->setProject($project) ->setUser($user); diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 17506bfe6c..406f64b370 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -11,6 +11,7 @@ class Audit extends Event protected string $mode = ''; protected string $userAgent = ''; protected string $ip = ''; + protected string $hostname = ''; public function __construct(protected Connection $connection) { @@ -113,6 +114,30 @@ class Audit extends Event return $this->ip; } + /** + * Set the hostname. + * + * @param string $hostname + * + * @return self + */ + public function setHostname(string $hostname): self + { + $this->hostname = $hostname; + + return $this; + } + + /** + * Get the hostname. + * + * @return string + */ + public function getHostname(): string + { + return $this->hostname; + } + /** * Executes the event and sends it to the audit worker. * @@ -136,6 +161,7 @@ class Audit extends Event 'ip' => $this->ip, 'userAgent' => $this->userAgent, 'event' => $this->event, + 'hostname' => $this->hostname ]); } } From b7651e4f5e30d825d3f95c9a475b92b775ed0f36 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Fri, 3 Jan 2025 15:56:36 +0530 Subject: [PATCH 207/340] address comment: add files/buckets to common. --- app/config/collections.php | 8 +- app/config/collections/buckets.php | 270 ----------------------------- app/config/collections/common.php | 265 ++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 274 deletions(-) delete mode 100644 app/config/collections/buckets.php diff --git a/app/config/collections.php b/app/config/collections.php index d490a1dc99..d966412382 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1,15 +1,15 @@ <?php -use Utopia\Config\Config; $common = include __DIR__ . '/collections/common.php'; -$buckets = include __DIR__ . '/collections/buckets.php'; $projects = include __DIR__ . '/collections/projects.php'; $databases = include __DIR__ . '/collections/databases.php'; $platform = include __DIR__ . '/collections/platform.php'; -$auth = Config::getParam('auth', []); -$providers = Config::getParam('oAuthProviders', []); +$buckets = $common['files']; + +// no more required. +unset($common['files']); /** * $collection => id of the parent collection where this will be inserted diff --git a/app/config/collections/buckets.php b/app/config/collections/buckets.php deleted file mode 100644 index 289e351f35..0000000000 --- a/app/config/collections/buckets.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -use Utopia\Database\Database; -use Utopia\Database\Helpers\ID; - -return [ - 'files' => [ - '$collection' => ID::custom('buckets'), - '$id' => ID::custom('files'), - '$name' => 'Files', - 'attributes' => [ - [ - 'array' => false, - '$id' => ID::custom('bucketId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('bucketInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('signature'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('metadata'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('sizeOriginal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sizeActual'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('algorithm'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('comment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLCipher'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLTag'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLIV'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksUploaded'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_bucket'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['bucketId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_signature'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['signature'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_mimeType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['mimeType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_sizeOriginal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['sizeOriginal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksTotal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksTotal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksUploaded'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksUploaded'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ] - ], -]; diff --git a/app/config/collections/common.php b/app/config/collections/common.php index 1280595221..a613e8f3ab 100644 --- a/app/config/collections/common.php +++ b/app/config/collections/common.php @@ -2354,4 +2354,269 @@ return [ ], ], ], + + // note that this is not required for console & projects. + 'files' => [ + '$collection' => ID::custom('buckets'), + '$id' => ID::custom('files'), + '$name' => 'Files', + 'attributes' => [ + [ + 'array' => false, + '$id' => ID::custom('bucketId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('bucketInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('path'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('signature'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('metadata'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('sizeOriginal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sizeActual'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('algorithm'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('comment'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLCipher'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLTag'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLIV'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksUploaded'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_bucket'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['bucketId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_signature'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['signature'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_mimeType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['mimeType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_sizeOriginal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['sizeOriginal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksTotal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksTotal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksUploaded'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksUploaded'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ] + ], ]; From 7910d5652da460a9b10f8ba4149f02c56adfe330 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Fri, 3 Jan 2025 17:20:27 +0530 Subject: [PATCH 208/340] fix: collection creation and tests. --- app/config/collections.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index d966412382..8c8356aafd 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -6,7 +6,9 @@ $projects = include __DIR__ . '/collections/projects.php'; $databases = include __DIR__ . '/collections/databases.php'; $platform = include __DIR__ . '/collections/platform.php'; -$buckets = $common['files']; +// see - http.php#245 +// $collections['buckets']['files']; +$buckets = ['files' => $common['files']]; // no more required. unset($common['files']); From e1c08e33d402c13718caeb612778b99bd102cf4c Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Sat, 4 Jan 2025 12:51:42 +0530 Subject: [PATCH 209/340] fix: trigger webhooks events only if a project has webhooks --- app/controllers/shared/api.php | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 012dd13c73..5c1251da08 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -58,7 +58,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar return $label; }; -$eventDatabaseListener = function (Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { +$eventDatabaseListener = function (Document $project,Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { // Only trigger events for user creation with the database listener. if ($document->getCollection() !== 'users') { return; @@ -74,17 +74,20 @@ $eventDatabaseListener = function (Document $document, Response $response, Event ->from($queueForEvents) ->trigger(); - $queueForWebhooks - ->from($queueForEvents) - ->trigger(); - if ($queueForEvents->getProject()->getId() === 'console') { - return; + /** Trigger webhooks events only if a project has them enabled */ + if ($project->getAttribute('webhooks', []) !== []) { + $queueForWebhooks + ->from($queueForEvents) + ->trigger(); } - $queueForRealtime - ->from($queueForEvents) - ->trigger(); + /** Trigger realtime events only for non console events */ + if ($queueForEvents->getProject()->getId() !== 'console') { + $queueForRealtime + ->from($queueForEvents) + ->trigger(); + } }; $usageDatabaseListener = function (string $event, Document $document, Usage $queueForUsage) { @@ -526,6 +529,7 @@ App::init() ->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage)) ->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage)) ->on(Database::EVENT_DOCUMENT_CREATE, 'create-trigger-events', fn ($event, $document) => $eventDatabaseListener( + $project, $document, $response, $queueForEventsClone->from($queueForEvents), @@ -678,10 +682,6 @@ App::shutdown() $queueForEvents->setPayload($responsePayload); } - $queueForWebhooks - ->from($queueForEvents) - ->trigger(); - $queueForFunctions ->from($queueForEvents) ->trigger(); @@ -691,6 +691,13 @@ App::shutdown() ->from($queueForEvents) ->trigger(); } + + /** Trigger webhooks events only if a project has them enabled */ + if ($project->getAttribute('webhooks', []) !== []) { + $queueForWebhooks + ->from($queueForEvents) + ->trigger(); + } } $route = $utopia->getRoute(); From 56af9d09913502729548f27b3981eb2251be2191 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Sat, 4 Jan 2025 12:51:50 +0530 Subject: [PATCH 210/340] chore: add todo --- app/controllers/shared/api.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 5c1251da08..38755b9bfb 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -692,7 +692,11 @@ App::shutdown() ->trigger(); } - /** Trigger webhooks events only if a project has them enabled */ + /** Trigger webhooks events only if a project has them enabled + * A future optimisation is to only trigger webhooks if the webhook is "enabled" + * But it might have performance implications on the API due to the number of webhooks etc. + * Some profiling is needed to see if this is a problem. + */ if ($project->getAttribute('webhooks', []) !== []) { $queueForWebhooks ->from($queueForEvents) From bdb6599087e05cac48e3a5a3395ce7d991069fb3 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Sat, 4 Jan 2025 12:55:20 +0530 Subject: [PATCH 211/340] chore: linter --- app/controllers/shared/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 38755b9bfb..592c7b8a49 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -58,7 +58,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar return $label; }; -$eventDatabaseListener = function (Document $project,Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { +$eventDatabaseListener = function (Document $project, Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { // Only trigger events for user creation with the database listener. if ($document->getCollection() !== 'users') { return; @@ -692,7 +692,7 @@ App::shutdown() ->trigger(); } - /** Trigger webhooks events only if a project has them enabled + /** Trigger webhooks events only if a project has them enabled * A future optimisation is to only trigger webhooks if the webhook is "enabled" * But it might have performance implications on the API due to the number of webhooks etc. * Some profiling is needed to see if this is a problem. From 1a73847c4798e77923da52a1f231f9fc7bb0cf70 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 11:28:26 +0200 Subject: [PATCH 212/340] added operations debug header --- app/controllers/api/databases.php | 67 ++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index c3f74389cc..16258e9972 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2944,7 +2944,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $data['$permissions'] = $permissions; $document = new Document($data); - $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database) { + $operations = 1; + + $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { $documentSecurity = $collection->getAttribute('documentSecurity', false); $validator = new Authorization($permission); @@ -2976,10 +2978,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') if ($isList) { $relations = $related; + $operations += count($related); } else { $relations = [$related]; + $operations++; } + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) @@ -3026,6 +3031,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ; + try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); } catch (StructureException $e) { @@ -3036,7 +3046,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; + $operations = 0; // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { @@ -3078,8 +3088,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection @@ -3238,6 +3248,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); } + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) + ; + $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); }, false); @@ -3265,11 +3280,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } } - $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; - $response->addHeader('X-Debug-Operations', $operations); $response->dynamic(new Document([ 'total' => $total, @@ -3586,7 +3596,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { + + $operations = 1; + + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { $relationships = \array_filter( $collection->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP @@ -3595,6 +3608,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); + /** + * Write relationship counts + */ + if (\in_array(\gettype($related), ['array', 'object'])) { + + } + if (empty($related)) { continue; } @@ -3603,8 +3623,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if ($isList) { $relations = $related; + $operations += count($related); } else { $relations = [$related]; + $operations++; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); @@ -3654,6 +3676,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection($collection, $newDocument); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ; + try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, @@ -3673,7 +3700,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; + $operations = 0; // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { @@ -3715,8 +3742,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $processDocument($collection, $document); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; $response->addHeader('X-Debug-Operations', $operations); @@ -3843,6 +3870,15 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $processDocument($collection, $document); + $queueForUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) + ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + + + $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( @@ -3859,11 +3895,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setContext('database', $database) ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); - $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) - ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - $response->addHeader('X-Debug-Operations', $operations); $response->noContent(); }); From 895e79e7369715be206e01cfdf8fe3eca3376450 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Mon, 6 Jan 2025 12:25:56 +0200 Subject: [PATCH 213/340] Operations --- app/controllers/api/databases.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 16258e9972..ac41f2d2fe 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2944,7 +2944,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $data['$permissions'] = $permissions; $document = new Document($data); - $operations = 1; + $operations = 1; // For root createDocument $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { $documentSecurity = $collection->getAttribute('documentSecurity', false); @@ -3046,7 +3046,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 0; + $operations = 0; // Since the Document is sent through post no getDocument used // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { @@ -3597,7 +3597,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $newDocument = new Document($data); - $operations = 1; + $operations = 1; // Root updateDocument $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { $relationships = \array_filter( @@ -3700,7 +3700,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 0; + $operations = 1; // Since we read original Document // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { @@ -3811,6 +3811,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $operations = 1; // Read original Document + // Read permission should not be required for delete $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); @@ -3829,8 +3831,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; - // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { $document->setAttribute('$databaseId', $database->getId()); @@ -3877,8 +3877,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - - $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( From 1bc419b6a1dc697cb106b47ca674e4f5b661db48 Mon Sep 17 00:00:00 2001 From: Fabian Gruber <fabian@appwrite.io> Date: Mon, 6 Jan 2025 13:48:01 +0100 Subject: [PATCH 214/340] feat(swoole): allow configuration override of available cpus --- app/http.php | 2 +- app/init.php | 2 +- app/realtime.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/http.php b/app/http.php index 61afce3eae..3a7562ffd1 100644 --- a/app/http.php +++ b/app/http.php @@ -42,7 +42,7 @@ $http = new Server( ); $payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing -$totalWorkers = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); $http ->set([ diff --git a/app/init.php b/app/init.php index c6847610c2..7f95ac4c25 100644 --- a/app/init.php +++ b/app/init.php @@ -895,7 +895,7 @@ $register->set('pools', function () { $multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled'; if ($multiprocessing) { - $workerCount = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); + $workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); } else { $workerCount = 1; } diff --git a/app/realtime.php b/app/realtime.php index 4f87e4dea1..86f9c85fdd 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -193,7 +193,7 @@ $stats->create(); $containerId = uniqid(); $statsDocument = null; -$workerNumber = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$workerNumber = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); $adapter = new Adapter\Swoole(port: System::getEnv('PORT', 80)); $adapter From 0814fe49e204221ac86f021f325cc1c0fd92cd25 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 16:50:23 +0200 Subject: [PATCH 215/340] added operations debug header --- app/controllers/api/databases.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 16258e9972..8f59033795 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3031,11 +3031,14 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ; + $response->addHeader('X-Debug-operations-write', $operations); + try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); } catch (StructureException $e) { @@ -3092,8 +3095,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - - $response->addHeader('X-Debug-Operations', $operations); + $response->addHeader('X-Debug-operations-read', $operations); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($document, Response::MODEL_DOCUMENT); @@ -3253,6 +3255,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; + $response->addHeader('X-Debug-operations-reads', $operations); + $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); }, false); @@ -3280,7 +3284,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') } } - $response->addHeader('X-Debug-Operations', $operations); $response->dynamic(new Document([ 'total' => $total, 'documents' => $documents, @@ -3388,7 +3391,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; - $response->addHeader('X-Debug-Operations', $operations); + $response->addHeader('X-Debug-operations-reads', $operations); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3681,6 +3684,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ; + $response->addHeader('X-Debug-operations-writes', $operations); + try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, @@ -3746,7 +3751,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; - $response->addHeader('X-Debug-Operations', $operations); + $response->addHeader('X-Debug-operations-reads', $operations); + $response->dynamic($document, Response::MODEL_DOCUMENT); $relationships = \array_map( From f70222d41a532d00bb2db34a767bc64c7f2e96f4 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 17:19:39 +0200 Subject: [PATCH 216/340] added operations debug header --- app/controllers/api/databases.php | 35 ++++++++++--------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 3f8fe7cfdc..fa12087463 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2944,8 +2944,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $data['$permissions'] = $permissions; $document = new Document($data); - $operations = 1; // For root createDocument - + $operations = 1; $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { $documentSecurity = $collection->getAttribute('documentSecurity', false); $validator = new Authorization($permission); @@ -3031,14 +3030,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $checkPermissions($collection, $document, Database::PERMISSION_CREATE); - - $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) - ; - - $response->addHeader('X-Debug-operations-write', $operations); - try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); } catch (StructureException $e) { @@ -3049,10 +3040,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 0; // Since the Document is sent through post no getDocument used // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3064,10 +3054,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - if (empty($related)) { continue; } @@ -3091,11 +3077,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - $response->addHeader('X-Debug-operations-read', $operations); + $response->addHeader('X-Debug-Operations', $operations); + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($document, Response::MODEL_DOCUMENT); @@ -3255,7 +3242,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; - $response->addHeader('X-Debug-operations-reads', $operations); + $response->addHeader('X-Debug-Operations', $operations); $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); @@ -3391,7 +3378,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ; - $response->addHeader('X-Debug-operations-reads', $operations); + $response->addHeader('X-Debug-Operations', $operations); + $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3600,8 +3588,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $newDocument = new Document($data); - $operations = 1; // Root updateDocument - + $operations = 1; $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { $relationships = \array_filter( $collection->getAttribute('attributes', []), @@ -3684,7 +3671,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ; - $response->addHeader('X-Debug-operations-writes', $operations); + $response->addHeader('X-Debug-Operations', $operations); try { $document = $dbForProject->withRequestTimestamp( From fc03075ef895d4818029445d6af32fd55cfd4ae0 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Mon, 6 Jan 2025 18:01:44 +0200 Subject: [PATCH 217/340] Update counts --- app/controllers/api/databases.php | 28 +++++++++++--------- composer.lock | 44 +++++++++++++++---------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index fa12087463..f6de0d7d0f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3163,7 +3163,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } - $documentId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); @@ -3178,7 +3177,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); - $operations = 1; + $operations = 0; // Add $collectionId and $databaseId for all documents $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { @@ -3186,6 +3185,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') return false; } + $operations++; + $document->removeAttribute('$collection'); $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3198,13 +3199,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { + if (\gettype($related) === 'object'){ $operations++; + } else if(\gettype($related) === 'array'){ + $operations += max(1, count($related)); } if (empty($related)) { continue; } + if (!\is_array($related)) { $relations = [$related]; } else { @@ -3328,7 +3332,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DOCUMENT_NOT_FOUND); } - $operations = 1; + $operations = 0; // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { @@ -3336,6 +3340,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen return; } + $operations++; + $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3347,13 +3353,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { + if (\gettype($related) === 'object'){ $operations++; + } else if(\gettype($related) === 'array'){ + $operations += max(1, count($related)); } if (empty($related)) { continue; } + if (!\is_array($related)) { $related = [$related]; } @@ -3587,8 +3596,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $operations = 1; + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { $relationships = \array_filter( $collection->getAttribute('attributes', []), @@ -3598,13 +3607,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - /** - * Write relationship counts - */ - if (\in_array(\gettype($related), ['array', 'object'])) { - - } - if (empty($related)) { continue; } diff --git a/composer.lock b/composer.lock index ce5f358619..dbe9e079b5 100644 --- a/composer.lock +++ b/composer.lock @@ -2453,16 +2453,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.1", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" + "reference": "339ba21476eb184290361542f732ad12c97591ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", - "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", + "reference": "339ba21476eb184290361542f732ad12c97591ec", "shasum": "" }, "require": { @@ -2528,7 +2528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.1" + "source": "https://github.com/symfony/http-client/tree/v7.2.2" }, "funding": [ { @@ -2544,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2024-12-30T18:35:15+00:00" }, { "name": "symfony/http-client-contracts", @@ -5126,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": { @@ -5146,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" @@ -5188,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", @@ -7735,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": { @@ -7779,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": [ { @@ -7795,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", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From d64ea97ee6ff6f895477cb4b54166e9f6261c0e3 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 18:06:18 +0200 Subject: [PATCH 218/340] added operations debug header --- app/controllers/api/databases.php | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index fa12087463..c65c76297d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3692,10 +3692,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; // Since we read original Document - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3707,10 +3705,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - if (empty($related)) { continue; } @@ -3733,13 +3727,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $processDocument($collection, $document); - $queueForUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) - ; - - $response->addHeader('X-Debug-operations-reads', $operations); - $response->dynamic($document, Response::MODEL_DOCUMENT); $relationships = \array_map( From 40b407027efb1ddcb453b6570cd033ed004ff717 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Mon, 6 Jan 2025 18:51:39 +0200 Subject: [PATCH 219/340] Count changes --- app/controllers/api/databases.php | 49 ++++++++++++------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index b9614f5ef9..ca81519834 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2944,8 +2944,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $data['$permissions'] = $permissions; $document = new Document($data); - $operations = 1; + $operations = 0; + $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { + $operations++; + $documentSecurity = $collection->getAttribute('documentSecurity', false); $validator = new Authorization($permission); @@ -2977,13 +2980,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') if ($isList) { $relations = $related; - $operations += count($related); } else { $relations = [$related]; - $operations++; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) @@ -3102,8 +3102,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->setContext('collection', $collection) ->setContext('database', $database) ->setPayload($response->getPayload(), sensitive: $relationships); - - }); App::get('/v1/databases/:databaseId/collections/:collectionId/documents') @@ -3199,13 +3197,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\gettype($related) === 'object'){ - $operations++; - } else if(\gettype($related) === 'array'){ - $operations += max(1, count($related)); - } - if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + continue; } @@ -3353,13 +3349,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\gettype($related) === 'object'){ - $operations++; - } else if(\gettype($related) === 'array'){ - $operations += max(1, count($related)); - } - if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + continue; } @@ -3596,9 +3590,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $operations = 1; + $operations = 0; $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + + $operations++; + $relationships = \array_filter( $collection->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP @@ -3615,10 +3612,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum if ($isList) { $relations = $related; - $operations += count($related); } else { $relations = [$related]; - $operations++; } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); @@ -3793,8 +3788,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; // Read original Document - // Read permission should not be required for delete $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); @@ -3814,7 +3807,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3826,10 +3819,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - if (empty($related)) { continue; } @@ -3855,8 +3844,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection $relationships = \array_map( @@ -3875,7 +3862,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setContext('database', $database) ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); - $response->addHeader('X-Debug-Operations', $operations); + $response->addHeader('X-Debug-Operations', 1); $response->noContent(); }); From a481e958e345b220a98b252277043cd4de8eac47 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 18:57:35 +0200 Subject: [PATCH 220/340] added operations debug header --- app/controllers/api/databases.php | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index b9614f5ef9..5503a78051 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3078,7 +3078,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES), $operations) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection $response->addHeader('X-Debug-Operations', $operations); @@ -3102,8 +3102,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->setContext('collection', $collection) ->setContext('database', $database) ->setPayload($response->getPayload(), sensitive: $relationships); - - }); App::get('/v1/databases/:databaseId/collections/:collectionId/documents') @@ -3177,9 +3175,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); - $operations = 0; - // Add $collectionId and $databaseId for all documents + $operations = 1; $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { if ($document->isEmpty()) { return false; @@ -3332,9 +3329,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DOCUMENT_NOT_FOUND); } - $operations = 0; - // Add $collectionId and $databaseId for all documents + $operations = 1; $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { if ($document->isEmpty()) { return; @@ -3491,6 +3487,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); } } + $response->dynamic(new Document([ 'total' => $audit->countLogsByResource($resource), 'logs' => $output, @@ -3597,7 +3594,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $newDocument = new Document($data); $operations = 1; - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { $relationships = \array_filter( $collection->getAttribute('attributes', []), @@ -3793,8 +3789,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $operations = 1; // Read original Document - // Read permission should not be required for delete $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); @@ -3814,7 +3808,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu } // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3826,10 +3820,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu foreach ($relationships as $relationship) { $related = $document->getAttribute($relationship->getAttribute('key')); - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - if (empty($related)) { continue; } @@ -3855,10 +3845,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $queueForUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + $response->addHeader('X-Debug-Operations', $operations); + $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( @@ -3875,7 +3865,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setContext('database', $database) ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); - $response->addHeader('X-Debug-Operations', $operations); $response->noContent(); }); From 5c097df56a1710925fbb3bbe0973380147975b21 Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 19:07:18 +0200 Subject: [PATCH 221/340] added operations debug header --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 92e61ad1d5..347b4ebbef 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3847,7 +3847,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - $response->addHeader('X-Debug-Operations', $operations); + $response->addHeader('X-Debug-Operations', 1); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), From f2cbdbae870babc3c92fca3d10d0c4a255e4ecdf Mon Sep 17 00:00:00 2001 From: shimon <shimon@appwrite.io> Date: Mon, 6 Jan 2025 19:32:19 +0200 Subject: [PATCH 222/340] added operations debug header --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index dbe9e079b5..b906af3a81 100644 --- a/composer.lock +++ b/composer.lock @@ -8580,5 +8580,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } From 077313fe2d40be73756c4334c150b248841cbad6 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 15:46:35 +1300 Subject: [PATCH 223/340] Update src/Appwrite/Platform/Workers/Databases.php --- src/Appwrite/Platform/Workers/Databases.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 74c1250505..c16fba36c1 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -284,9 +284,6 @@ class Databases extends Action $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } - /** - * No throwing Exception - */ } catch (\Throwable $e) { Console::error($e->getMessage()); From 2c04ace02236fb01c2aed9229d5da1ecab63e813 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 18:38:24 +1300 Subject: [PATCH 224/340] Add connection for project --- app/init.php | 31 +++++++++++++++++++++++-------- app/worker.php | 39 +++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/app/init.php b/app/init.php index b4e60d7924..51d9c38239 100644 --- a/app/init.php +++ b/app/init.php @@ -74,6 +74,7 @@ use Utopia\Logger\Adapter\Raygun; use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Logger; +use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Pools\Pool; use Utopia\Queue; @@ -1412,7 +1413,26 @@ App::setResource('console', function () { ]); }, []); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('connectionForProject', function (Group $pools, Document $project) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $pools + ->get('console') + ->pop(); + } + + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + + return $pools + ->get($dsn->getHost()) + ->pop(); +}, ['pools', 'project']); + +App::setResource('dbForProject', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -1424,12 +1444,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $database = new Database($connectionForProject->getResource(), $cache); $database ->setMetadata('host', \gethostname()) @@ -1452,7 +1467,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache', 'project']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $dbAdapter = $pools diff --git a/app/worker.php b/app/worker.php index 6eb1363e9b..845af12efc 100644 --- a/app/worker.php +++ b/app/worker.php @@ -16,6 +16,7 @@ use Appwrite\Event\Migration; use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; +use Swoole\Database\DetectsLostConnections; use Swoole\Runtime; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; @@ -25,11 +26,13 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; +use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Queue\Connection; use Utopia\Queue\Message; @@ -66,13 +69,13 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { +Server::setResource('connectionForProject', function (Group $pools, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForPlatform; + return $pools + ->get('console') + ->pop(); } - $pools = $register->get('pools'); - try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -80,12 +83,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $adapter = $pools + return $pools ->get($dsn->getHost()) - ->pop() - ->getResource(); + ->pop(); +}, ['pools', 'project']); - $database = new Database($adapter, $cache); +Server::setResource('dbForProject', function (PoolConnection $connectionForProject, Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $dbForPlatform; + } + + $database = new Database($connectionForProject->getResource(), $cache); try { $dsn = new DSN($project->getAttribute('database')); @@ -109,12 +117,12 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, } return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['connectionForProject', 'cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $connectionForProject, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -146,12 +154,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf return $database; } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $database = new Database($connectionForProject->getResource(), $cache); $databases[$dsn->getHost()] = $database; @@ -171,7 +174,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); From 71b892132bc4ef7d57ee813bd0d1a6cc307dc3d7 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 18:39:06 +1300 Subject: [PATCH 225/340] Mark connections as unhealthy on lost connection error from DB --- app/controllers/general.php | 14 +++++++++++++- app/worker.php | 11 ++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index db9df71341..90cb3293e6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -21,6 +21,7 @@ use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; +use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Utopia\App; use Utopia\CLI\Console; @@ -28,6 +29,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -38,6 +40,7 @@ use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Logger\Logger; +use Utopia\Pools\Connection; use Utopia\System\System; use Utopia\Validator\Hostname; use Utopia\Validator\Text; @@ -746,7 +749,16 @@ App::error() ->inject('logger') ->inject('log') ->inject('queueForUsage') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { + ->inject('connectionForProject') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage, Connection $connectionForProject) { + if ( + ($error instanceof PDOException || $error instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($error) + ) { + // Mark connection as unhealthy so it will be recycled on next reclaim. + $connectionForProject->setHealthy(false); + } + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); diff --git a/app/worker.php b/app/worker.php index 845af12efc..62882b32b1 100644 --- a/app/worker.php +++ b/app/worker.php @@ -413,7 +413,16 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) { + ->inject('connectionForProject') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, PoolConnection $connectionForProject) use ($queueName) { + if ( + ($error instanceof PDOException || $error instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($error) + ) { + // Mark connection as unhealthy, it will be recycled on next reclaim. + $connectionForProject->setHealthy(false); + } + $pools->reclaim(); $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); From 38ee612164c3be3206fd1eaf6288cc37eadede94 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 18:39:26 +1300 Subject: [PATCH 226/340] Update pools --- composer.json | 2 +- composer.lock | 49 +++++++++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index e44dd0bffc..ebbcad4673 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.5.*", + "utopia-php/pools": "dev-feat-connection-health as 0.5.0", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index b906af3a81..90d2d3fe71 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": "6b136b5490c0d5d331eac0d70bb3e198", + "content-hash": "59c7d90abfa068a55426b786a244d985", "packages": [ { "name": "adhocore/jwt", @@ -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", @@ -4145,25 +4145,25 @@ }, { "name": "utopia-php/pools", - "version": "0.5.0", + "version": "dev-feat-connection-health", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" + "reference": "b1d35f023b3ccf0d171fad88cc833cdace0e1e67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/b1d35f023b3ccf0d171fad88cc833cdace0e1e67", + "reference": "b1d35f023b3ccf0d171fad88cc833cdace0e1e67", "shasum": "" }, "require": { - "php": ">=8.0" + "php": ">=8.3" }, "require-dev": { - "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.8.*", - "phpunit/phpunit": "^9.3" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*" }, "type": "library", "autoload": { @@ -4190,9 +4190,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.5.0" + "source": "https://github.com/utopia-php/pools/tree/feat-connection-health" }, - "time": "2024-04-19T11:11:54+00:00" + "time": "2025-01-08T03:56:11+00:00" }, { "name": "utopia-php/preloader", @@ -8554,9 +8554,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/pools", + "version": "dev-feat-connection-health", + "alias": "0.5.0", + "alias_normalized": "0.5.0.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/pools": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8580,5 +8589,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } From 02ab3c850ee660caac70959ab1b5ba87106ded39 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Wed, 8 Jan 2025 06:40:33 +0000 Subject: [PATCH 227/340] Update SDK Generator versions --- app/config/platforms.php | 2 +- composer.json | 2 +- composer.lock | 30 +++++++++---------- .../databases/update-boolean-attribute.md | 3 +- .../databases/update-datetime-attribute.md | 3 +- .../databases/update-email-attribute.md | 3 +- .../databases/update-enum-attribute.md | 3 +- .../databases/update-float-attribute.md | 3 +- .../databases/update-integer-attribute.md | 3 +- .../examples/databases/update-ip-attribute.md | 3 +- .../update-relationship-attribute.md | 1 + .../databases/update-string-attribute.md | 4 ++- .../databases/update-url-attribute.md | 3 +- .../projects/update-memberships-privacy.md | 5 ++++ .../databases/update-string-attribute.md | 2 +- .../projects/update-memberships-privacy.md | 16 ++++++++++ .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../server-graphql/examples/account/create.md | 1 + .../server-graphql/examples/account/get.md | 1 + .../examples/account/update-email.md | 1 + .../examples/account/update-m-f-a.md | 1 + .../account/update-mfa-authenticator.md | 1 + .../examples/account/update-name.md | 1 + .../examples/account/update-password.md | 1 + .../examples/account/update-phone.md | 1 + .../examples/account/update-prefs.md | 1 + .../examples/account/update-status.md | 1 + .../databases/create-boolean-attribute.md | 2 ++ .../examples/databases/create-collection.md | 2 ++ .../databases/create-datetime-attribute.md | 2 ++ .../databases/create-email-attribute.md | 2 ++ .../databases/create-enum-attribute.md | 2 ++ .../databases/create-float-attribute.md | 2 ++ .../examples/databases/create-index.md | 2 ++ .../databases/create-integer-attribute.md | 2 ++ .../examples/databases/create-ip-attribute.md | 2 ++ .../create-relationship-attribute.md | 2 ++ .../databases/create-string-attribute.md | 2 ++ .../databases/create-url-attribute.md | 2 ++ .../examples/databases/get-collection.md | 2 ++ .../examples/databases/get-index.md | 2 ++ .../examples/databases/list-collections.md | 2 ++ .../examples/databases/list-indexes.md | 2 ++ .../databases/update-boolean-attribute.md | 2 ++ .../examples/databases/update-collection.md | 2 ++ .../databases/update-datetime-attribute.md | 2 ++ .../databases/update-email-attribute.md | 2 ++ .../databases/update-enum-attribute.md | 2 ++ .../databases/update-float-attribute.md | 2 ++ .../databases/update-integer-attribute.md | 2 ++ .../examples/databases/update-ip-attribute.md | 2 ++ .../update-relationship-attribute.md | 2 ++ .../databases/update-string-attribute.md | 4 ++- .../databases/update-url-attribute.md | 2 ++ .../examples/messaging/create-subscriber.md | 1 + .../examples/messaging/get-subscriber.md | 1 + .../examples/messaging/list-subscribers.md | 1 + .../examples/messaging/list-targets.md | 1 + .../examples/users/create-argon2user.md | 1 + .../examples/users/create-bcrypt-user.md | 1 + .../examples/users/create-m-d5user.md | 1 + .../examples/users/create-p-h-pass-user.md | 1 + .../examples/users/create-s-h-a-user.md | 1 + .../users/create-scrypt-modified-user.md | 1 + .../examples/users/create-scrypt-user.md | 1 + .../examples/users/create-target.md | 1 + .../server-graphql/examples/users/create.md | 1 + .../users/delete-mfa-authenticator.md | 1 + .../examples/users/get-target.md | 1 + .../server-graphql/examples/users/get.md | 1 + .../examples/users/list-targets.md | 1 + .../server-graphql/examples/users/list.md | 1 + .../users/update-email-verification.md | 1 + .../examples/users/update-email.md | 1 + .../examples/users/update-labels.md | 1 + .../examples/users/update-mfa.md | 1 + .../examples/users/update-name.md | 1 + .../examples/users/update-password.md | 1 + .../users/update-phone-verification.md | 1 + .../examples/users/update-phone.md | 1 + .../examples/users/update-status.md | 1 + .../examples/users/update-target.md | 1 + .../java/databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../account/create-anonymous-session.md | 1 + .../account/create-email-password-session.md | 1 + .../examples/account/create-email-token.md | 1 + .../examples/account/create-j-w-t.md | 1 + .../account/create-magic-u-r-l-token.md | 1 + .../account/create-mfa-authenticator.md | 1 + .../examples/account/create-mfa-challenge.md | 1 + .../account/create-mfa-recovery-codes.md | 1 + .../examples/account/create-o-auth2token.md | 1 + .../examples/account/create-phone-token.md | 1 + .../account/create-phone-verification.md | 1 + .../examples/account/create-recovery.md | 1 + .../examples/account/create-session.md | 1 + .../examples/account/create-verification.md | 1 + .../server-python/examples/account/create.md | 1 + .../examples/account/delete-identity.md | 1 + .../account/delete-mfa-authenticator.md | 1 + .../examples/account/delete-session.md | 1 + .../examples/account/delete-sessions.md | 1 + .../account/get-mfa-recovery-codes.md | 1 + .../examples/account/get-prefs.md | 1 + .../examples/account/get-session.md | 1 + .../server-python/examples/account/get.md | 1 + .../examples/account/list-identities.md | 1 + .../examples/account/list-logs.md | 1 + .../examples/account/list-mfa-factors.md | 1 + .../examples/account/list-sessions.md | 1 + .../examples/account/update-email.md | 1 + .../examples/account/update-m-f-a.md | 1 + .../account/update-magic-u-r-l-session.md | 1 + .../account/update-mfa-authenticator.md | 1 + .../examples/account/update-mfa-challenge.md | 1 + .../account/update-mfa-recovery-codes.md | 1 + .../examples/account/update-name.md | 1 + .../examples/account/update-password.md | 1 + .../examples/account/update-phone-session.md | 1 + .../account/update-phone-verification.md | 1 + .../examples/account/update-phone.md | 1 + .../examples/account/update-prefs.md | 1 + .../examples/account/update-recovery.md | 1 + .../examples/account/update-session.md | 1 + .../examples/account/update-status.md | 1 + .../examples/account/update-verification.md | 1 + .../examples/avatars/get-browser.md | 1 + .../examples/avatars/get-credit-card.md | 1 + .../examples/avatars/get-favicon.md | 1 + .../examples/avatars/get-flag.md | 1 + .../examples/avatars/get-image.md | 1 + .../examples/avatars/get-initials.md | 1 + .../server-python/examples/avatars/get-q-r.md | 1 + .../databases/create-boolean-attribute.md | 1 + .../examples/databases/create-collection.md | 1 + .../databases/create-datetime-attribute.md | 1 + .../examples/databases/create-document.md | 1 + .../databases/create-email-attribute.md | 1 + .../databases/create-enum-attribute.md | 1 + .../databases/create-float-attribute.md | 1 + .../examples/databases/create-index.md | 1 + .../databases/create-integer-attribute.md | 1 + .../examples/databases/create-ip-attribute.md | 1 + .../create-relationship-attribute.md | 1 + .../databases/create-string-attribute.md | 1 + .../databases/create-url-attribute.md | 1 + .../examples/databases/create.md | 1 + .../examples/databases/delete-attribute.md | 1 + .../examples/databases/delete-collection.md | 1 + .../examples/databases/delete-document.md | 1 + .../examples/databases/delete-index.md | 1 + .../examples/databases/delete.md | 1 + .../examples/databases/get-attribute.md | 1 + .../examples/databases/get-collection.md | 1 + .../examples/databases/get-document.md | 1 + .../examples/databases/get-index.md | 1 + .../server-python/examples/databases/get.md | 1 + .../examples/databases/list-attributes.md | 1 + .../examples/databases/list-collections.md | 1 + .../examples/databases/list-documents.md | 1 + .../examples/databases/list-indexes.md | 1 + .../server-python/examples/databases/list.md | 1 + .../databases/update-boolean-attribute.md | 1 + .../examples/databases/update-collection.md | 1 + .../databases/update-datetime-attribute.md | 1 + .../examples/databases/update-document.md | 1 + .../databases/update-email-attribute.md | 1 + .../databases/update-enum-attribute.md | 1 + .../databases/update-float-attribute.md | 1 + .../databases/update-integer-attribute.md | 1 + .../examples/databases/update-ip-attribute.md | 1 + .../update-relationship-attribute.md | 1 + .../databases/update-string-attribute.md | 3 +- .../databases/update-url-attribute.md | 1 + .../examples/databases/update.md | 1 + .../examples/functions/create-build.md | 1 + .../examples/functions/create-deployment.md | 1 + .../examples/functions/create-execution.md | 1 + .../examples/functions/create-variable.md | 1 + .../examples/functions/create.md | 1 + .../examples/functions/delete-deployment.md | 1 + .../examples/functions/delete-execution.md | 1 + .../examples/functions/delete-variable.md | 1 + .../examples/functions/delete.md | 1 + .../functions/get-deployment-download.md | 1 + .../examples/functions/get-deployment.md | 1 + .../examples/functions/get-execution.md | 1 + .../examples/functions/get-variable.md | 1 + .../server-python/examples/functions/get.md | 1 + .../examples/functions/list-deployments.md | 1 + .../examples/functions/list-executions.md | 1 + .../examples/functions/list-runtimes.md | 1 + .../examples/functions/list-specifications.md | 1 + .../examples/functions/list-variables.md | 1 + .../server-python/examples/functions/list.md | 1 + .../functions/update-deployment-build.md | 1 + .../examples/functions/update-deployment.md | 1 + .../examples/functions/update-variable.md | 1 + .../examples/functions/update.md | 1 + .../examples/graphql/mutation.md | 1 + .../server-python/examples/graphql/query.md | 1 + .../examples/health/get-antivirus.md | 1 + .../examples/health/get-cache.md | 1 + .../examples/health/get-certificate.md | 1 + .../server-python/examples/health/get-d-b.md | 1 + .../examples/health/get-failed-jobs.md | 1 + .../examples/health/get-pub-sub.md | 1 + .../examples/health/get-queue-builds.md | 1 + .../examples/health/get-queue-certificates.md | 1 + .../examples/health/get-queue-databases.md | 1 + .../examples/health/get-queue-deletes.md | 1 + .../examples/health/get-queue-functions.md | 1 + .../examples/health/get-queue-logs.md | 1 + .../examples/health/get-queue-mails.md | 1 + .../examples/health/get-queue-messaging.md | 1 + .../examples/health/get-queue-migrations.md | 1 + .../examples/health/get-queue-usage-dump.md | 1 + .../examples/health/get-queue-usage.md | 1 + .../examples/health/get-queue-webhooks.md | 1 + .../examples/health/get-queue.md | 1 + .../examples/health/get-storage-local.md | 1 + .../examples/health/get-storage.md | 1 + .../server-python/examples/health/get-time.md | 1 + .../server-python/examples/health/get.md | 1 + .../server-python/examples/locale/get.md | 1 + .../examples/locale/list-codes.md | 1 + .../examples/locale/list-continents.md | 1 + .../examples/locale/list-countries-e-u.md | 1 + .../examples/locale/list-countries-phones.md | 1 + .../examples/locale/list-countries.md | 1 + .../examples/locale/list-currencies.md | 1 + .../examples/locale/list-languages.md | 1 + .../messaging/create-apns-provider.md | 1 + .../examples/messaging/create-email.md | 1 + .../examples/messaging/create-fcm-provider.md | 1 + .../messaging/create-mailgun-provider.md | 1 + .../messaging/create-msg91provider.md | 1 + .../examples/messaging/create-push.md | 1 + .../messaging/create-sendgrid-provider.md | 1 + .../examples/messaging/create-sms.md | 1 + .../messaging/create-smtp-provider.md | 1 + .../examples/messaging/create-subscriber.md | 1 + .../messaging/create-telesign-provider.md | 1 + .../messaging/create-textmagic-provider.md | 1 + .../examples/messaging/create-topic.md | 1 + .../messaging/create-twilio-provider.md | 1 + .../messaging/create-vonage-provider.md | 1 + .../examples/messaging/delete-provider.md | 1 + .../examples/messaging/delete-subscriber.md | 1 + .../examples/messaging/delete-topic.md | 1 + .../examples/messaging/delete.md | 1 + .../examples/messaging/get-message.md | 1 + .../examples/messaging/get-provider.md | 1 + .../examples/messaging/get-subscriber.md | 1 + .../examples/messaging/get-topic.md | 1 + .../examples/messaging/list-message-logs.md | 1 + .../examples/messaging/list-messages.md | 1 + .../examples/messaging/list-provider-logs.md | 1 + .../examples/messaging/list-providers.md | 1 + .../messaging/list-subscriber-logs.md | 1 + .../examples/messaging/list-subscribers.md | 1 + .../examples/messaging/list-targets.md | 1 + .../examples/messaging/list-topic-logs.md | 1 + .../examples/messaging/list-topics.md | 1 + .../messaging/update-apns-provider.md | 1 + .../examples/messaging/update-email.md | 1 + .../examples/messaging/update-fcm-provider.md | 1 + .../messaging/update-mailgun-provider.md | 1 + .../messaging/update-msg91provider.md | 1 + .../examples/messaging/update-push.md | 1 + .../messaging/update-sendgrid-provider.md | 1 + .../examples/messaging/update-sms.md | 1 + .../messaging/update-smtp-provider.md | 1 + .../messaging/update-telesign-provider.md | 1 + .../messaging/update-textmagic-provider.md | 1 + .../examples/messaging/update-topic.md | 1 + .../messaging/update-twilio-provider.md | 1 + .../messaging/update-vonage-provider.md | 1 + .../examples/storage/create-bucket.md | 1 + .../examples/storage/create-file.md | 1 + .../examples/storage/delete-bucket.md | 1 + .../examples/storage/delete-file.md | 1 + .../examples/storage/get-bucket.md | 1 + .../examples/storage/get-file-download.md | 1 + .../examples/storage/get-file-preview.md | 1 + .../examples/storage/get-file-view.md | 1 + .../examples/storage/get-file.md | 1 + .../examples/storage/list-buckets.md | 1 + .../examples/storage/list-files.md | 1 + .../examples/storage/update-bucket.md | 1 + .../examples/storage/update-file.md | 1 + .../examples/teams/create-membership.md | 1 + .../server-python/examples/teams/create.md | 1 + .../examples/teams/delete-membership.md | 1 + .../server-python/examples/teams/delete.md | 1 + .../examples/teams/get-membership.md | 1 + .../server-python/examples/teams/get-prefs.md | 1 + .../1.6.x/server-python/examples/teams/get.md | 1 + .../examples/teams/list-memberships.md | 1 + .../server-python/examples/teams/list.md | 1 + .../teams/update-membership-status.md | 1 + .../examples/teams/update-membership.md | 1 + .../examples/teams/update-name.md | 1 + .../examples/teams/update-prefs.md | 1 + .../examples/users/create-argon2user.md | 1 + .../examples/users/create-bcrypt-user.md | 1 + .../examples/users/create-j-w-t.md | 1 + .../examples/users/create-m-d5user.md | 1 + .../users/create-mfa-recovery-codes.md | 1 + .../examples/users/create-p-h-pass-user.md | 1 + .../examples/users/create-s-h-a-user.md | 1 + .../users/create-scrypt-modified-user.md | 1 + .../examples/users/create-scrypt-user.md | 1 + .../examples/users/create-session.md | 1 + .../examples/users/create-target.md | 1 + .../examples/users/create-token.md | 1 + .../server-python/examples/users/create.md | 1 + .../examples/users/delete-identity.md | 1 + .../users/delete-mfa-authenticator.md | 1 + .../examples/users/delete-session.md | 1 + .../examples/users/delete-sessions.md | 1 + .../examples/users/delete-target.md | 1 + .../server-python/examples/users/delete.md | 1 + .../examples/users/get-mfa-recovery-codes.md | 1 + .../server-python/examples/users/get-prefs.md | 1 + .../examples/users/get-target.md | 1 + .../1.6.x/server-python/examples/users/get.md | 1 + .../examples/users/list-identities.md | 1 + .../server-python/examples/users/list-logs.md | 1 + .../examples/users/list-memberships.md | 1 + .../examples/users/list-mfa-factors.md | 1 + .../examples/users/list-sessions.md | 1 + .../examples/users/list-targets.md | 1 + .../server-python/examples/users/list.md | 1 + .../users/update-email-verification.md | 1 + .../examples/users/update-email.md | 1 + .../examples/users/update-labels.md | 1 + .../users/update-mfa-recovery-codes.md | 1 + .../examples/users/update-mfa.md | 1 + .../examples/users/update-name.md | 1 + .../examples/users/update-password.md | 1 + .../users/update-phone-verification.md | 1 + .../examples/users/update-phone.md | 1 + .../examples/users/update-prefs.md | 1 + .../examples/users/update-status.md | 1 + .../examples/users/update-target.md | 1 + .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- .../databases/update-string-attribute.md | 2 +- 355 files changed, 427 insertions(+), 40 deletions(-) create mode 100644 docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md create mode 100644 docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md diff --git a/app/config/platforms.php b/app/config/platforms.php index 167e55651c..849733d359 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '6.0.0', + 'version' => '6.2.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/composer.json b/composer.json index e44dd0bffc..c6c2cdb950 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.39.28", + "appwrite/sdk-generator": "0.39.29", "phpunit/phpunit": "9.5.20", "swoole/ide-helper": "5.1.2", "textalk/websocket": "1.5.7", diff --git a/composer.lock b/composer.lock index b906af3a81..54aca6fd30 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": "6b136b5490c0d5d331eac0d70bb3e198", + "content-hash": "819d7979e0239b187e2a1875d97ed0cf", "packages": [ { "name": "adhocore/jwt", @@ -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", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.28", + "version": "0.39.29", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "6ff467858fe418e364460da905139216570a5d5e" + "reference": "a9c3f6076ec162588dac7b0a741bc1a2c3d1a2b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6ff467858fe418e364460da905139216570a5d5e", - "reference": "6ff467858fe418e364460da905139216570a5d5e", + "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.28" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.29" }, - "time": "2024-12-30T11:17:25+00:00" + "time": "2025-01-07T05:28:35+00:00" }, { "name": "doctrine/annotations", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8580,5 +8580,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md index d48c3470fe..f5adb497ec 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateBooleanAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default false + --default false \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md index 9fc56373ed..fe4a462664 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateDatetimeAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default '' + --default '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md index 9f7bffeb9c..58510a6f8e 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateEmailAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default email@example.com + --default email@example.com \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md index bf562a0a82..21d56d3e64 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md @@ -4,4 +4,5 @@ appwrite databases updateEnumAttribute \ --key '' \ --elements one two three \ --required false \ - --default <DEFAULT> + --default <DEFAULT> \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md index 097dfd310a..353320d78a 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md @@ -5,4 +5,5 @@ appwrite databases updateFloatAttribute \ --required false \ --min null \ --max null \ - --default null + --default null \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md index 6a6b0747a8..c170b7f6fa 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md @@ -5,4 +5,5 @@ appwrite databases updateIntegerAttribute \ --required false \ --min null \ --max null \ - --default null + --default null \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md index 2439b5a8de..a400eadc1e 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateIpAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default '' + --default '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md index be03a70736..6e2dbd927d 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md @@ -3,3 +3,4 @@ appwrite databases updateRelationshipAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md index ebf45253fa..526ece0b72 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md @@ -3,4 +3,6 @@ appwrite databases updateStringAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default <DEFAULT> + --default <DEFAULT> \ + + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md index aa11a588db..e6f401b8ca 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateUrlAttribute \ --collectionId <COLLECTION_ID> \ --key '' \ --required false \ - --default https://example.com + --default https://example.com \ + diff --git a/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md b/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..6c811ccfce --- /dev/null +++ b/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md @@ -0,0 +1,5 @@ +appwrite projects updateMembershipsPrivacy \ + --projectId <PROJECT_ID> \ + --userName false \ + --userEmail false \ + --mfa false diff --git a/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md index 0ac1497d00..f652c304eb 100644 --- a/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md @@ -12,7 +12,7 @@ const result = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md b/docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..2cde25faa5 --- /dev/null +++ b/docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md @@ -0,0 +1,16 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateMembershipsPrivacy( + '<PROJECT_ID>', // projectId + false, // userName + false, // userEmail + false // mfa +); + +console.log(result); diff --git a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md index c2f3804c66..f9498aa36b 100644 --- a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ AttributeString result = await databases.updateStringAttribute( key: '', xrequired: false, xdefault: '<DEFAULT>', - size: 0, // (optional) + size: 1, // (optional) newKey: '', // (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md index 6603c377cb..d57f8fd663 100644 --- a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const response = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md index e915d23f51..a180815a50 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ AttributeString result = await databases.UpdateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md index d662060f09..f3e6addb07 100644 --- a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md @@ -20,7 +20,7 @@ func main() { "", false, "<DEFAULT>", - databases.WithUpdateStringAttributeSize(0), + databases.WithUpdateStringAttributeSize(1), databases.WithUpdateStringAttributeNewKey(""), ) diff --git a/docs/examples/1.6.x/server-graphql/examples/account/create.md b/docs/examples/1.6.x/server-graphql/examples/account/create.md index 3f8e3c3cf7..0d39394a3d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/create.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/get.md b/docs/examples/1.6.x/server-graphql/examples/account/get.md index e4db8f0e41..f4f07c187f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/get.md @@ -28,6 +28,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md index b207bad4bb..c879e24a43 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md index d2cd3d6ae5..787c2e0860 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md index c74062c7d4..9cfe9150be 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md index 850b5760a0..8ba2c99d9c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md index 5904da0842..f3619a10d2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md index 408a203300..adecb71168 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md index 40db7b43db..57280247e4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md index aca8c098e7..c17f556842 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md @@ -28,6 +28,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md index 6e969a587e..aa0bfa832e 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md index 05175cc1e7..51eb51f410 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md index fcd5cb37a2..47601df0d8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md index 1f23a23ba7..e5845ccd47 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md index 410a7983b4..d13c080e4a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md index ae6f9f72d6..2a270c3aff 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md index efc92a798c..2875a9b4b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md @@ -13,5 +13,7 @@ mutation { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md index 1dc43f6b0d..8c79706817 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md index b2fd7215a0..0f4ad9e139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md index ddca20b83a..f66b87d6af 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md index 3c290712e9..62d97d6962 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md index d2a39756c9..89ad873e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md index f76b71b6ba..ed27286b0d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md @@ -19,6 +19,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md index de3c44ebe0..29de7a76f8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md @@ -10,5 +10,7 @@ query { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md index b821b6c4cf..8dafbf7042 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md @@ -22,6 +22,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md index e1c11b6c03..3cb67c6451 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md @@ -12,6 +12,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md index e92b41a14e..d508e62139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md index fc78bb8efc..e918c058b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md index 46d9bbb728..a21b910edc 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md index e05d365162..6c83d80e16 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md index 619cbf817c..378e32f9b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md index 7641745a35..c5c7afca44 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md index 11b7a66014..e38ccaa88c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md index 649fa881b5..7a26224200 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md index 88ba2f9636..6694540d93 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md @@ -12,6 +12,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md index 4d88462efb..afafb307f5 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md @@ -5,7 +5,7 @@ mutation { key: "", required: false, default: "<DEFAULT>", - size: 0, + size: 1, newKey: "" ) { key @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md index 06838a9ed4..f9f14a04f6 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md index b2712ebb48..bab53612b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md @@ -17,6 +17,7 @@ mutation { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md index 54096dd70a..2e1672d010 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md @@ -16,6 +16,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md index 5c48ae34bb..a5a4f91e56 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md @@ -19,6 +19,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md index 8e356dce5f..aa82276de2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md index 464dc754c9..7f99622e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md index 4d4bb09194..26659176eb 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md index e8e833e6de..7e642b8233 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md index 53960e7890..4c06b007a2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md index 17e287f8b3..f99da2752d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md index 6d51fb29ba..624ffcdd38 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md @@ -36,6 +36,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md index 0d4bac1db8..68a5f4c75f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md @@ -38,6 +38,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md index a3a0696dec..7068c21aba 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md @@ -15,5 +15,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create.md b/docs/examples/1.6.x/server-graphql/examples/users/create.md index 826a5168ef..465da80432 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md index 227c340c68..26c9594a53 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md index e4ba1a04a1..c84f947898 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md @@ -11,5 +11,6 @@ query { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get.md b/docs/examples/1.6.x/server-graphql/examples/users/get.md index f94a5818ed..9d0be685d9 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get.md @@ -30,6 +30,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md index 05e796f167..408fd96f80 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list.md b/docs/examples/1.6.x/server-graphql/examples/users/list.md index e2326dd1a2..a90121adf2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list.md @@ -33,6 +33,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md index 6bb2781854..cda7278ac0 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md index 046937ac04..408a74972b 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md index 93da33d805..cb3c5b6483 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md index 9219aa1aea..ac09ea19a4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md index 01a53ce479..ec7e3dc27c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md index c95637c4ce..95ef74c83d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md index 58343ae365..c6afa54ba4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md index dbcb076c65..d3fc7d5f37 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md index ad05bc75ff..2499c1c258 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md index fe3444ede7..1f7cc1147a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md @@ -14,5 +14,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md index 75be9e01f8..2d69006181 100644 --- a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md @@ -15,7 +15,7 @@ databases.updateStringAttribute( "", // key false, // required "<DEFAULT>", // default - 0, // size (optional) + 1, // size (optional) "", // newKey (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md index a37d4566ee..32e17beb9c 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md @@ -15,6 +15,6 @@ val response = databases.updateStringAttribute( key = "", required = false, default = "<DEFAULT>", - size = 0, // optional + size = 1, // optional newKey = "" // optional ) diff --git a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md index f379fdc0cf..6aecbb591e 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const result = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md index 9e821e4436..721ba324de 100644 --- a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md @@ -16,6 +16,6 @@ $result = $databases->updateStringAttribute( key: '', required: false, default: '<DEFAULT>', - size: null, // optional + size: 1, // optional newKey: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md b/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md index 36ed47de01..ce5a92ad18 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md b/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md index b85cc3d365..5e869fd40c 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-email-token.md b/docs/examples/1.6.x/server-python/examples/account/create-email-token.md index 4c18324ef3..5cf2bfb085 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-email-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-email-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md b/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md index 2121514562..c737f1b8e9 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md b/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md index c0154182e6..00778172bb 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md index 16a8e2ebae..a6f09eb4f0 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md index 017fdd28cc..deb4c9c600 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticationFactor client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md index 452b47f72f..a149cb95b7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md b/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md index 0cc89df216..fa11d31c31 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import OAuthProvider client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md b/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md index 30c80df6be..d242d71bc1 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md b/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md index fd0a2620aa..bb2058eb2a 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-recovery.md b/docs/examples/1.6.x/server-python/examples/account/create-recovery.md index e9613cd947..3d215a400e 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-recovery.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-recovery.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-session.md b/docs/examples/1.6.x/server-python/examples/account/create-session.md index d129e1000c..d00e8cb899 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-verification.md b/docs/examples/1.6.x/server-python/examples/account/create-verification.md index 5ff238f674..329d19e6fd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create.md b/docs/examples/1.6.x/server-python/examples/account/create.md index 33b6f3fe23..39b33c62ee 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create.md +++ b/docs/examples/1.6.x/server-python/examples/account/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-identity.md b/docs/examples/1.6.x/server-python/examples/account/delete-identity.md index ef57289443..3556122de8 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-identity.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-identity.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md index 0fbe8c7475..939ea718c7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-session.md b/docs/examples/1.6.x/server-python/examples/account/delete-session.md index fa0049c6e4..9ddb4431d3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md b/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md index 6ebe286c89..751ab9bb2d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md index ec705952b2..f70b968274 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-prefs.md b/docs/examples/1.6.x/server-python/examples/account/get-prefs.md index 67d0741733..52df6450dc 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-session.md b/docs/examples/1.6.x/server-python/examples/account/get-session.md index f7ae72d69e..f38466fb34 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get.md b/docs/examples/1.6.x/server-python/examples/account/get.md index 9ded8e96cb..b414047e2d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get.md +++ b/docs/examples/1.6.x/server-python/examples/account/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-identities.md b/docs/examples/1.6.x/server-python/examples/account/list-identities.md index c51da2cb67..4bf9beb1b2 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-identities.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-identities.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-logs.md b/docs/examples/1.6.x/server-python/examples/account/list-logs.md index 750f97716a..5d8c27aded 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-logs.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md b/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md index 2220475b9f..ba3796bf65 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-sessions.md b/docs/examples/1.6.x/server-python/examples/account/list-sessions.md index b3427c09ce..74733138cd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-email.md b/docs/examples/1.6.x/server-python/examples/account/update-email.md index b0a2a16002..004d071da1 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md b/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md index 561e7cc431..2f9321c485 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md b/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md index f6b69b03cc..ca8e8e51a3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md index 42b91f1d46..a5a951906c 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md index 5964df42f8..d28a2518d7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md index 4f0b1362a0..38cb41ca8d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-name.md b/docs/examples/1.6.x/server-python/examples/account/update-name.md index d0027a8400..9b4bf8291d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-password.md b/docs/examples/1.6.x/server-python/examples/account/update-password.md index 888349e207..ecb4228df0 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-password.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-password.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md b/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md index 404d2b458c..d29ab28e39 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md b/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md index 41ceb4bc05..e64d79f6bd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone.md b/docs/examples/1.6.x/server-python/examples/account/update-phone.md index b7414e613e..65a6a387b3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-prefs.md b/docs/examples/1.6.x/server-python/examples/account/update-prefs.md index f69dc12b33..c3683007b7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-recovery.md b/docs/examples/1.6.x/server-python/examples/account/update-recovery.md index a3314134e6..2493dc5e53 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-recovery.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-recovery.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-session.md b/docs/examples/1.6.x/server-python/examples/account/update-session.md index 3768326e98..ee3a2f7543 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-status.md b/docs/examples/1.6.x/server-python/examples/account/update-status.md index 4f9add80f7..c8318a43ce 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-status.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-verification.md b/docs/examples/1.6.x/server-python/examples/account/update-verification.md index 35faf53cb8..63a7f26322 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md b/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md index 91dde3bbb8..7ed831835f 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import Browser client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md b/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md index cec2f61a20..aa66b86b2d 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import CreditCard client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md b/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md index 4aa0177a26..2c6a67e2f2 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md b/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md index 6b12dac6be..435c8550f7 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import Flag client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-image.md b/docs/examples/1.6.x/server-python/examples/avatars/get-image.md index 202955c2fc..ee9e0cb15e 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-image.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-image.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md b/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md index 233da1b131..edcbbb33ec 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md b/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md index 12963947d2..7f6da32ddf 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md index 183a2b6487..2b4209db9d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-collection.md b/docs/examples/1.6.x/server-python/examples/databases/create-collection.md index fd9e3a6c0c..99c44a2f9f 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md index 7435742e1c..db81c021e2 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-document.md b/docs/examples/1.6.x/server-python/examples/databases/create-document.md index bd3993f162..22f2c07396 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md index f4b427e294..2e28e0bfff 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md index dce63558da..b1efdc7dc3 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md index a658bd8f4c..b36863b8ee 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-index.md b/docs/examples/1.6.x/server-python/examples/databases/create-index.md index 015b762bbc..9885c06e95 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases from appwrite.enums import IndexType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md index 9f409e484e..8cb140a7b9 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md index ab4d357447..d4b4ab6528 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md index 76b5db1c45..4172c27249 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases from appwrite.enums import RelationshipType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md index d6f7f94627..e69687124d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md index 3b105d80e8..4ad03c4010 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create.md b/docs/examples/1.6.x/server-python/examples/databases/create.md index a4ddc92cc6..d5cbb99eed 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md index 7f490b2350..b317ba9dd4 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md b/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md index c3083a51bc..ab274c6bdf 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-document.md b/docs/examples/1.6.x/server-python/examples/databases/delete-document.md index c3e296aef2..69151aad9e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-index.md b/docs/examples/1.6.x/server-python/examples/databases/delete-index.md index d5a12c140e..2ed0165b36 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete.md b/docs/examples/1.6.x/server-python/examples/databases/delete.md index 41d5f18f8a..e7e988a9a5 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md index e505fe9a38..a717552659 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-collection.md b/docs/examples/1.6.x/server-python/examples/databases/get-collection.md index 7be57ea193..f63298ebed 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-document.md b/docs/examples/1.6.x/server-python/examples/databases/get-document.md index 83faadec38..acdc25de7e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-index.md b/docs/examples/1.6.x/server-python/examples/databases/get-index.md index 6038868b41..ca5a9958ad 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get.md b/docs/examples/1.6.x/server-python/examples/databases/get.md index 8fe2358be7..deadf6ab41 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md b/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md index a29aefa015..245ec60c19 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-collections.md b/docs/examples/1.6.x/server-python/examples/databases/list-collections.md index 0e613321c2..ca18267250 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-collections.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-collections.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-documents.md b/docs/examples/1.6.x/server-python/examples/databases/list-documents.md index dee130e65f..41f0380e15 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-documents.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-documents.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md b/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md index 40578a14de..bf18bd1c95 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list.md b/docs/examples/1.6.x/server-python/examples/databases/list.md index aa934b2b12..11669b3453 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md index 553d94b109..c9300ea57d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-collection.md b/docs/examples/1.6.x/server-python/examples/databases/update-collection.md index 3432b6bf18..d9297285ee 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md index f9056d2c39..96c7fb5439 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-document.md b/docs/examples/1.6.x/server-python/examples/databases/update-document.md index 07bba7678c..7b9cce9513 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md index 45a8d0d9bc..5b042d4b72 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md index c07f3754d8..caa1b4ecdb 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md index fa1767e893..8f8a35a2c8 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md index 0db97070ed..125cf825bf 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md index 135dbd82ea..a2b8bad201 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md index bc528f17dd..0aacc139a0 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md index bbe7ddb19f..c85eb25f59 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint @@ -13,6 +14,6 @@ result = databases.update_string_attribute( key = '', required = False, default = '<DEFAULT>', - size = None, # optional + size = 1, # optional new_key = '' # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md index 8e3a28de1f..53da6ae45f 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update.md b/docs/examples/1.6.x/server-python/examples/databases/update.md index 765f28a3fc..da59776b3e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-build.md b/docs/examples/1.6.x/server-python/examples/functions/create-build.md index c4eb9d0a20..ce2ffb72f5 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-build.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-build.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md index da9b559b2f..c86fdf679d 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions from appwrite.input_file import InputFile client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-execution.md b/docs/examples/1.6.x/server-python/examples/functions/create-execution.md index e1decb9755..cb3fddd02b 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-variable.md b/docs/examples/1.6.x/server-python/examples/functions/create-variable.md index cd73e30c03..101ecdf315 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create.md b/docs/examples/1.6.x/server-python/examples/functions/create.md index a65b87dd4c..f10a953ca8 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions from appwrite.enums import client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md index 780ce9d7c8..f98bd60a9b 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md b/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md index 7c3ea09a0f..b723fd6c47 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md b/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md index 646a0f325b..e17afed363 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete.md b/docs/examples/1.6.x/server-python/examples/functions/delete.md index 2950ed0235..a34d476744 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md index 490d9521df..90f029aff5 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md index 8846888f0f..0617b0429c 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-execution.md b/docs/examples/1.6.x/server-python/examples/functions/get-execution.md index f3dfc0f4ee..0a9a347409 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-variable.md b/docs/examples/1.6.x/server-python/examples/functions/get-variable.md index fd903f3045..174c8b27bf 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get.md b/docs/examples/1.6.x/server-python/examples/functions/get.md index cb765e42a1..a463fa6b28 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md b/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md index f776345f11..4d8feea927 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-executions.md b/docs/examples/1.6.x/server-python/examples/functions/list-executions.md index 0012bafc8f..293bab047a 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-executions.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-executions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md b/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md index edad1a9178..b6247330d0 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md b/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md index a9c7417654..5e1ec7fd61 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-variables.md b/docs/examples/1.6.x/server-python/examples/functions/list-variables.md index 188c17bb6a..ee1a516c5e 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-variables.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-variables.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list.md b/docs/examples/1.6.x/server-python/examples/functions/list.md index 5b315e18cc..0b5f18d70a 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md b/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md index a8d93b8416..c69cd7c181 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md index 9fce384715..0f4c96e85c 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-variable.md b/docs/examples/1.6.x/server-python/examples/functions/update-variable.md index 238fc91eff..bcab3685a2 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update.md b/docs/examples/1.6.x/server-python/examples/functions/update.md index 5f2a70baaa..a7282412cc 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/graphql/mutation.md b/docs/examples/1.6.x/server-python/examples/graphql/mutation.md index 0ec3d3eefc..e05f602719 100644 --- a/docs/examples/1.6.x/server-python/examples/graphql/mutation.md +++ b/docs/examples/1.6.x/server-python/examples/graphql/mutation.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.graphql import Graphql client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/graphql/query.md b/docs/examples/1.6.x/server-python/examples/graphql/query.md index 95709fd694..c8f3c78a1a 100644 --- a/docs/examples/1.6.x/server-python/examples/graphql/query.md +++ b/docs/examples/1.6.x/server-python/examples/graphql/query.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.graphql import Graphql client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md b/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md index ff93ceac76..7bc0475abf 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-cache.md b/docs/examples/1.6.x/server-python/examples/health/get-cache.md index fa2a6daa5c..7e69825ecf 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-cache.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-cache.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-certificate.md b/docs/examples/1.6.x/server-python/examples/health/get-certificate.md index 2a73583361..f6a713e2f3 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-certificate.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-certificate.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-d-b.md b/docs/examples/1.6.x/server-python/examples/health/get-d-b.md index 18e3968246..a23a073ac7 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-d-b.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-d-b.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md b/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md index ce33c8c9bd..d0fe64f7f3 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health from appwrite.enums import client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md b/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md index db66c7f676..109b2889f6 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md index 9daed589f8..b1d4d62116 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md index a7d35bc9f4..99f52b8eda 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md index 50f8943fa6..7d5e5a0c58 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md index b6e6a4d4a4..d677af582e 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md index 5868b3cd68..3ffc4b8f52 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md index 254fe23331..0cb6417f4f 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md index c6ab409c9b..97a501cc1c 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md index 1007913866..ea93eab6dc 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md index db59028f37..09e35dfa9d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md index cc31b4f5af..dabb79ae96 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md index 67d9e64c14..dbee75fce0 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md index 918846738d..1072a20def 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue.md b/docs/examples/1.6.x/server-python/examples/health/get-queue.md index 61e5a40caa..aafe7c7dd0 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md b/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md index 276c3058f9..d3b94b2177 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-storage.md b/docs/examples/1.6.x/server-python/examples/health/get-storage.md index b2de63b72f..65af2f959d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-storage.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-storage.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-time.md b/docs/examples/1.6.x/server-python/examples/health/get-time.md index 40893057cb..d63beb988b 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-time.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-time.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get.md b/docs/examples/1.6.x/server-python/examples/health/get.md index f41e0e3a9b..f5c494e12d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get.md +++ b/docs/examples/1.6.x/server-python/examples/health/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/get.md b/docs/examples/1.6.x/server-python/examples/locale/get.md index fc048ddcc9..a44f4974ac 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/get.md +++ b/docs/examples/1.6.x/server-python/examples/locale/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-codes.md b/docs/examples/1.6.x/server-python/examples/locale/list-codes.md index d516538cb9..12cd12ee70 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-codes.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-continents.md b/docs/examples/1.6.x/server-python/examples/locale/list-continents.md index f6d8495527..ea4ac5312d 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-continents.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-continents.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md index 8bdac2e5e3..7fb6aaa59e 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md index 516d822b59..aafdb3d547 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries.md index 8fcbe1aeb9..a2f1ec458d 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md b/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md index 4708498efb..39267c663c 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-languages.md b/docs/examples/1.6.x/server-python/examples/locale/list-languages.md index 9583cd8b3f..6dec1b9072 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-languages.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-languages.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md index 022209d1e6..700e909c44 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-email.md b/docs/examples/1.6.x/server-python/examples/messaging/create-email.md index 38005a3736..92353e22c2 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-email.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md index 84c38eae98..d13ba0213d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md index fa94da96c9..83899716d7 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md index 0cffc4e491..117c46edca 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md index ffed825a3d..ff2fb69842 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md index 6e9b812736..5d20cde78d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md b/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md index c3e7fe70bf..c7e66d8c75 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md index 24108d251f..85c58236c0 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md index 81b0c5f468..cb8f4f748d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md index b06033c5c5..b602213b78 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md index 6dc1030cd3..03287e8fac 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md index b0184b53b4..4dd16da3f0 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md index c73e941945..524348f085 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md index cfee0ad7a4..68416bd8c3 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md index 4d2bd6d015..2a1840d64d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md index 5d404d1875..94085ef86b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md index b270b2a708..1c2f5635da 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete.md b/docs/examples/1.6.x/server-python/examples/messaging/delete.md index c62c8c0d21..aee928a792 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-message.md b/docs/examples/1.6.x/server-python/examples/messaging/get-message.md index 4b4ef39203..9e32d80623 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-message.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-message.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md index fdf94f0304..6bc85f2710 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md index 7f8284f874..43185d7eb3 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md index 57c465b883..dea6cbfb6b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md index 752e449806..1c2ab0b035 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md b/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md index 7219f0948e..8457f99ad5 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md index 148814c46d..c8544fac1e 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md b/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md index 3e896954e4..258e7cd6e1 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md index 7efaeadedf..d2049bd560 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md b/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md index fe2442d806..ba9e09d8b9 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md b/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md index 062257154c..b941ccbd31 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md index de72a76a27..57ba7f8d31 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md b/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md index 1379708965..cb21567d42 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md index 2bfd3edfc1..3f0205d4ce 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-email.md b/docs/examples/1.6.x/server-python/examples/messaging/update-email.md index 6cff0ae6d8..b8f9d719c1 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md index 7ca9f381e6..862e579f53 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md index a89338df92..aa1d4e922c 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md index 4c61950050..2d4efdbd78 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md index 3c3965c3bd..6114cbd918 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md index 8b67b7a44f..e528bd543d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md b/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md index aadbd9aee8..7cb008736f 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md index 74232e983f..2d798d4e0e 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md index 264928178b..91de1f155c 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md index bbe4a93a50..c3031047c9 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md index ee4d00411e..160ac26b6b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md index 52eed3bb7b..865fcb5c1d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md index 7cb1594a81..8e01128bf2 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md index c6e9e33e02..7e321f12a3 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/create-file.md b/docs/examples/1.6.x/server-python/examples/storage/create-file.md index d275070bac..fa0b117b01 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/create-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/create-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage from appwrite.input_file import InputFile client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md index 77d72eb915..8cddfb9202 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/delete-file.md b/docs/examples/1.6.x/server-python/examples/storage/delete-file.md index 775065dc38..08bba5ca4b 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/delete-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/delete-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md index adb78e8b92..79f903f244 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md index b419ea0164..1a82b26c70 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md index 2e3b2acdc6..40f32f1f10 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md index 9ce04e2a49..3947c76761 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file.md b/docs/examples/1.6.x/server-python/examples/storage/get-file.md index 9f04ef4740..0c2d5e3b2c 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md b/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md index 84eab54286..88540cd5ce 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md +++ b/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/list-files.md b/docs/examples/1.6.x/server-python/examples/storage/list-files.md index 8a2aa6d9a3..e26ac2e5f3 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/list-files.md +++ b/docs/examples/1.6.x/server-python/examples/storage/list-files.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md index 4eea2a9ccb..61388b0923 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/update-file.md b/docs/examples/1.6.x/server-python/examples/storage/update-file.md index 0137af5849..336e8a0846 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/update-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/update-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/create-membership.md b/docs/examples/1.6.x/server-python/examples/teams/create-membership.md index 484629550d..1af9f252ab 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/create-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/create-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/create.md b/docs/examples/1.6.x/server-python/examples/teams/create.md index 544ee3a706..7085d39642 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/create.md +++ b/docs/examples/1.6.x/server-python/examples/teams/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md b/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md index 7f0cbd4ed6..adf065cd3c 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/delete.md b/docs/examples/1.6.x/server-python/examples/teams/delete.md index fc8415238e..762f532dbf 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/delete.md +++ b/docs/examples/1.6.x/server-python/examples/teams/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get-membership.md b/docs/examples/1.6.x/server-python/examples/teams/get-membership.md index 6075cc70d1..17bacff1d3 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md b/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md index d740e69e3b..035777d5cd 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get.md b/docs/examples/1.6.x/server-python/examples/teams/get.md index 6d44b80ee3..985924e10b 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md b/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md index f7a072a6d8..885a4c2822 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md +++ b/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/list.md b/docs/examples/1.6.x/server-python/examples/teams/list.md index afb5de1241..c92d4c9c13 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/list.md +++ b/docs/examples/1.6.x/server-python/examples/teams/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md b/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md index ee6d211081..ae6e524da5 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-membership.md b/docs/examples/1.6.x/server-python/examples/teams/update-membership.md index 672615026e..c50f345b88 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-name.md b/docs/examples/1.6.x/server-python/examples/teams/update-name.md index 693654d3d7..d25c8db1f2 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md b/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md index 46616011d6..9eca847a02 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md b/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md index 575aa42b30..3d65496573 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md b/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md index f6cd2fe591..76532a98f0 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md b/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md index a758d4e089..2e1fdf632f 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md b/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md index cabf875938..da9d471fe2 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md index 606878f1e9..a4477b0406 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md b/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md index 0d8f9907ac..363be4f92f 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md b/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md index b0ae799b64..bb78ff7b5c 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md index d7d17c4de0..1cfbcfc4b4 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md index 507fb1f892..2d1e72bf77 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-session.md b/docs/examples/1.6.x/server-python/examples/users/create-session.md index a2ba12a580..bebd46b022 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-session.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-target.md b/docs/examples/1.6.x/server-python/examples/users/create-target.md index 9ad8364ea3..c11c7ca233 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users from appwrite.enums import MessagingProviderType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/users/create-token.md b/docs/examples/1.6.x/server-python/examples/users/create-token.md index e2ef2f6969..00a0e78610 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-token.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create.md b/docs/examples/1.6.x/server-python/examples/users/create.md index c3e7fd5558..c8dac9feae 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create.md +++ b/docs/examples/1.6.x/server-python/examples/users/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-identity.md b/docs/examples/1.6.x/server-python/examples/users/delete-identity.md index 4c78038d11..85c5b6dee3 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-identity.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-identity.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md index c7101d119f..b22d391879 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-session.md b/docs/examples/1.6.x/server-python/examples/users/delete-session.md index c0fabdb19c..dda5713a9e 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-session.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md b/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md index 328a9eeb2f..268c311dd9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-target.md b/docs/examples/1.6.x/server-python/examples/users/delete-target.md index 5c2d9df8d8..38cc5a9a23 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete.md b/docs/examples/1.6.x/server-python/examples/users/delete.md index de8b35b513..090c20f5a9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md index b37739ccae..ec9986ce60 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-prefs.md b/docs/examples/1.6.x/server-python/examples/users/get-prefs.md index 23109a9696..eb14d3acb9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-target.md b/docs/examples/1.6.x/server-python/examples/users/get-target.md index d494460c5e..f549f08450 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get.md b/docs/examples/1.6.x/server-python/examples/users/get.md index d7dda45516..6e018c2b00 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get.md +++ b/docs/examples/1.6.x/server-python/examples/users/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-identities.md b/docs/examples/1.6.x/server-python/examples/users/list-identities.md index 7764d74268..b10c320cdd 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-identities.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-identities.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-logs.md b/docs/examples/1.6.x/server-python/examples/users/list-logs.md index d1c6b0abb7..10d8ae0d03 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-logs.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-memberships.md b/docs/examples/1.6.x/server-python/examples/users/list-memberships.md index 27db71f0c7..fbb3b4c05e 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-memberships.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-memberships.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md b/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md index 39aed0c173..1f40b1f538 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-sessions.md b/docs/examples/1.6.x/server-python/examples/users/list-sessions.md index fd091b9683..a9eead0d78 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-targets.md b/docs/examples/1.6.x/server-python/examples/users/list-targets.md index b5b67b96e3..47666467ff 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-targets.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-targets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list.md b/docs/examples/1.6.x/server-python/examples/users/list.md index b191f8ae73..4b09ca5f85 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list.md +++ b/docs/examples/1.6.x/server-python/examples/users/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md b/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md index 72ddf7a9bd..4623bc34b1 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-email.md b/docs/examples/1.6.x/server-python/examples/users/update-email.md index c977d95250..083715bbfa 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-labels.md b/docs/examples/1.6.x/server-python/examples/users/update-labels.md index 04c3999305..24c5b27034 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-labels.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-labels.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md index ca3b96aa8b..d0e4da4e4a 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-mfa.md b/docs/examples/1.6.x/server-python/examples/users/update-mfa.md index e145f9b259..efd6730a26 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-mfa.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-mfa.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-name.md b/docs/examples/1.6.x/server-python/examples/users/update-name.md index d546b95297..6014ef51a5 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-password.md b/docs/examples/1.6.x/server-python/examples/users/update-password.md index 0c7e7bf030..90ac15f565 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-password.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-password.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md b/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md index b13c4fba33..a62e6a8ceb 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-phone.md b/docs/examples/1.6.x/server-python/examples/users/update-phone.md index ecb01728e8..f522730003 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-phone.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-phone.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-prefs.md b/docs/examples/1.6.x/server-python/examples/users/update-prefs.md index ca6999c950..64d9df39f8 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-status.md b/docs/examples/1.6.x/server-python/examples/users/update-status.md index ebec495c33..8943ef59f5 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-status.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-target.md b/docs/examples/1.6.x/server-python/examples/users/update-target.md index f9bdfb43ef..89513850b0 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md index 197ea2767d..71a5302e1a 100644 --- a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md @@ -8,6 +8,6 @@ X-Appwrite-Key: <YOUR_API_KEY> { "required": false, "default": "<DEFAULT>", - "size": 0, + "size": 1, "newKey": } diff --git a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md index 3b3c5eb644..5e4ac573dc 100644 --- a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ result = databases.update_string_attribute( key: '', required: false, default: '<DEFAULT>', - size: null, # optional + size: 1, # optional new_key: '' # optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md index 5fafd5e72e..d3129dcce2 100644 --- a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md @@ -13,7 +13,7 @@ let attributeString = try await databases.updateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ) From 39f34135f0780babc4ee69f9bfe0ef7754ccc36a Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 20:43:45 +1300 Subject: [PATCH 228/340] Update pools --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 90d2d3fe71..5aa40556e2 100644 --- a/composer.lock +++ b/composer.lock @@ -4149,12 +4149,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "b1d35f023b3ccf0d171fad88cc833cdace0e1e67" + "reference": "3b1913e7e9cb01acac26215abb37eb767c0112ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/b1d35f023b3ccf0d171fad88cc833cdace0e1e67", - "reference": "b1d35f023b3ccf0d171fad88cc833cdace0e1e67", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/3b1913e7e9cb01acac26215abb37eb767c0112ee", + "reference": "3b1913e7e9cb01acac26215abb37eb767c0112ee", "shasum": "" }, "require": { @@ -4192,7 +4192,7 @@ "issues": "https://github.com/utopia-php/pools/issues", "source": "https://github.com/utopia-php/pools/tree/feat-connection-health" }, - "time": "2025-01-08T03:56:11+00:00" + "time": "2025-01-08T07:40:13+00:00" }, { "name": "utopia-php/preloader", From 7f6a43cf7b3bde76d4f4ce47dddbed74a7608a03 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 21:00:02 +1300 Subject: [PATCH 229/340] Update to release --- composer.json | 2 +- composer.lock | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index ebbcad4673..2612403c1a 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "dev-feat-connection-health as 0.5.0", + "utopia-php/pools": "0.6.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index 5aa40556e2..045ef31ffa 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": "59c7d90abfa068a55426b786a244d985", + "content-hash": "7b5b5926b452186543903eb539f59c2d", "packages": [ { "name": "adhocore/jwt", @@ -4145,16 +4145,16 @@ }, { "name": "utopia-php/pools", - "version": "dev-feat-connection-health", + "version": "0.6.0", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "3b1913e7e9cb01acac26215abb37eb767c0112ee" + "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/3b1913e7e9cb01acac26215abb37eb767c0112ee", - "reference": "3b1913e7e9cb01acac26215abb37eb767c0112ee", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/59414ab7b57728edfde6d5ccc5a2583b7967ac18", + "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18", "shasum": "" }, "require": { @@ -4190,9 +4190,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/feat-connection-health" + "source": "https://github.com/utopia-php/pools/tree/0.6.0" }, - "time": "2025-01-08T07:40:13+00:00" + "time": "2025-01-08T07:58:42+00:00" }, { "name": "utopia-php/preloader", @@ -8554,18 +8554,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/pools", - "version": "dev-feat-connection-health", - "alias": "0.5.0", - "alias_normalized": "0.5.0.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/pools": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 941c9f19055928e4eb7b3fc5761b7602df98a99a Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 8 Jan 2025 21:15:33 +1300 Subject: [PATCH 230/340] Add connection health check to http error handler --- app/http.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/http.php b/app/http.php index 3a7562ffd1..b988c7d8ac 100644 --- a/app/http.php +++ b/app/http.php @@ -5,6 +5,7 @@ require_once __DIR__ . '/../vendor/autoload.php'; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Constant; +use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; @@ -17,6 +18,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -346,6 +348,15 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $app->run($request, $response); } catch (\Throwable $th) { + if ( + ($th instanceof PDOException || $th instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($th) + ) { + // Mark connection as unhealthy so it will be recycled on next reclaim. + $connectionForProject = $app->getResource('connectionForProject'); + $connectionForProject->setHealthy(false); + } + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $logger = $app->getResource("logger"); From ff056fa1457f3096ff6fc7ef7456d0bb95979911 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Wed, 8 Jan 2025 17:01:01 +0530 Subject: [PATCH 231/340] chore: shifted authphone usage tracking to api calls --- app/controllers/api/account.php | 84 ++++++++++++++++++++- app/controllers/api/teams.php | 29 ++++++- src/Appwrite/Event/Messaging.php | 2 +- src/Appwrite/Platform/Workers/Messaging.php | 18 +---- 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 76a3ef8b61..40e248836b 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -17,6 +17,7 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Mail; use Appwrite\Event\Messaging; +use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; @@ -27,7 +28,9 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; +use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Audit\Audit as EventAudit; use Utopia\Config\Config; @@ -2315,7 +2318,10 @@ App::post('/v1/account/tokens/phone') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('locale') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale) { + ->inject('timelimit') + ->inject('queueForUsage') + ->inject('plan') + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, Usage $queueForUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2452,6 +2458,27 @@ App::post('/v1/account/tokens/phone') ->setMessage($messageDoc) ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('organizationId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } + } } // Set to unhashed secret for events and server responses @@ -3465,7 +3492,10 @@ App::post('/v1/account/verification/phone') ->inject('queueForMessaging') ->inject('project') ->inject('locale') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale) { + ->inject('timelimit') + ->inject('queueForUsage') + ->inject('plan') + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, Usage $queueForUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -3548,6 +3578,27 @@ App::post('/v1/account/verification/phone') ->setMessage($messageDoc) ->setRecipients([$user->getAttribute('phone')]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('organizationId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } + } } // Set to unhashed secret for events and server responses @@ -4026,7 +4077,10 @@ App::post('/v1/account/mfa/challenge') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('queueForMails') - ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails) { + ->inject('timelimit') + ->inject('queueForUsage') + ->inject('plan') + ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, Usage $queueForUsage, array $plan) { $expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM); $code = Auth::codeGenerator(); @@ -4074,6 +4128,7 @@ App::post('/v1/account/mfa/challenge') $message = $message->render(); + $phone = $user->getAttribute('phone'); $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage(new Document([ @@ -4082,8 +4137,29 @@ App::post('/v1/account/mfa/challenge') 'content' => $code, ], ])) - ->setRecipients([$user->getAttribute('phone')]) + ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('organizationId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } + } break; case Type::EMAIL: if (empty(System::getEnv('_APP_SMTP_HOST'))) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index f829800b98..216807fecf 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -8,6 +8,7 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Mail; use Appwrite\Event\Messaging; +use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Platform\Workers\Deletes; @@ -17,7 +18,9 @@ use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; +use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; @@ -423,7 +426,10 @@ App::post('/v1/teams/:teamId/memberships') ->inject('queueForMails') ->inject('queueForMessaging') ->inject('queueForEvents') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents) { + ->inject('timelimit') + ->inject('queueForUsage') + ->inject('plan') + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, Usage $queueForUsage, array $plan) { $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -691,6 +697,27 @@ App::post('/v1/teams/:teamId/memberships') ->setMessage($messageDoc) ->setRecipients([$phone]) ->setProviderType('SMS'); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('organizationId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } + } } } diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index ab9b1bee6b..755b8c9158 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -27,7 +27,7 @@ class Messaging extends Event /** * Sets type for the build event. * - * @param string $type Can be `MESSAGE_TYPE_INTERNAL` or `MESSAGE_TYPE_EXTERNAL`. + * @param string $type Can be `MESSAGE_SEND_TYPE_INTERNAL` or `MESSAGE_SEND_TYPE_EXTERNAL`. * @return self */ public function setType(string $type): self diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 58f6265ff4..1ff032c3e1 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -96,7 +96,7 @@ class Messaging extends Action $message = new Document($payload['message'] ?? []); $recipients = $payload['recipients'] ?? []; - $this->sendInternalSMSMessage($message, $project, $recipients, $queueForUsage, $log); + $this->sendInternalSMSMessage($message, $project, $recipients, $log); break; case MESSAGE_SEND_TYPE_EXTERNAL: $message = $dbForProject->getDocument('messages', $payload['messageId']); @@ -377,7 +377,7 @@ class Messaging extends Action } } - private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Usage $queueForUsage, Log $log): void + private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Log $log): void { if (empty(System::getEnv('_APP_SMS_PROVIDER')) || empty(System::getEnv('_APP_SMS_FROM'))) { throw new \Exception('Skipped SMS processing. Missing "_APP_SMS_PROVIDER" or "_APP_SMS_FROM" environment variables.'); @@ -456,24 +456,14 @@ class Messaging extends Action $adapter->getMaxMessagesPerRequest() ); - batch(\array_map(function ($batch) use ($message, $provider, $adapter, $project, $queueForUsage) { - return function () use ($batch, $message, $provider, $adapter, $project, $queueForUsage) { + batch(\array_map(function ($batch) use ($message, $provider, $adapter) { + return function () use ($batch, $message, $provider, $adapter) { $message->setAttribute('to', $batch); $data = $this->buildSmsMessage($message, $provider); try { $adapter->send($data); - - $countryCode = $adapter->getCountryCode($message['to'][0] ?? ''); - if (!empty($countryCode)) { - $queueForUsage - ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); - } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); } catch (\Throwable $th) { throw new \Exception('Failed sending to targets with error: ' . $th->getMessage()); } From 1f240ca27aa765727249beb20cac9e5e7bf5c254 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Wed, 8 Jan 2025 17:09:55 +0530 Subject: [PATCH 232/340] chore: moved non-countrycode tracking outside abuse --- app/controllers/api/account.php | 24 ++++++++++++------------ app/controllers/api/teams.php | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 40e248836b..b80cf0fd64 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2473,11 +2473,11 @@ App::post('/v1/account/tokens/phone') $queueForUsage ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); } } @@ -3593,11 +3593,11 @@ App::post('/v1/account/verification/phone') $queueForUsage ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); } } @@ -4154,11 +4154,11 @@ App::post('/v1/account/mfa/challenge') $queueForUsage ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); } break; case Type::EMAIL: diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 216807fecf..fc9f959ed2 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -712,11 +712,11 @@ App::post('/v1/teams/:teamId/memberships') $queueForUsage ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); } } } From 2178bb44cd01d3c8e0934e6266bf76379a97cd68 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Wed, 8 Jan 2025 17:14:07 +0530 Subject: [PATCH 233/340] fix: attribute --- app/controllers/api/account.php | 6 +++--- app/controllers/api/teams.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index b80cf0fd64..ff96acfc57 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2462,7 +2462,7 @@ App::post('/v1/account/tokens/phone') if (isset($plan['authPhone'])) { $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days $timelimit - ->setParam('{organizationId}', $project->getAttribute('organizationId')); + ->setParam('{organizationId}', $project->getAttribute('teamId')); $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { @@ -3582,7 +3582,7 @@ App::post('/v1/account/verification/phone') if (isset($plan['authPhone'])) { $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days $timelimit - ->setParam('{organizationId}', $project->getAttribute('organizationId')); + ->setParam('{organizationId}', $project->getAttribute('teamId')); $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { @@ -4143,7 +4143,7 @@ App::post('/v1/account/mfa/challenge') if (isset($plan['authPhone'])) { $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days $timelimit - ->setParam('{organizationId}', $project->getAttribute('organizationId')); + ->setParam('{organizationId}', $project->getAttribute('teamId')); $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index fc9f959ed2..461e90da58 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -701,7 +701,7 @@ App::post('/v1/teams/:teamId/memberships') if (isset($plan['authPhone'])) { $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days $timelimit - ->setParam('{organizationId}', $project->getAttribute('organizationId')); + ->setParam('{organizationId}', $project->getAttribute('teamId')); $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { From 88755e6d3863f8d10be1d2e101cb4bc32537860a Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Wed, 8 Jan 2025 18:21:35 +0530 Subject: [PATCH 234/340] update: add `sleep` to tests. --- tests/e2e/Services/Messaging/MessagingConsoleClientTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php index 1b0d840f96..a4b7750b58 100644 --- a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php +++ b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php @@ -54,6 +54,9 @@ class MessagingConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); + // required for Cloud x Audits + sleep(10); + $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], From addb56ab7da144b6c55d79bd37c717f63ebb49e8 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Wed, 8 Jan 2025 18:24:53 +0530 Subject: [PATCH 235/340] update: shift comment. --- tests/e2e/Services/Messaging/MessagingConsoleClientTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php index a4b7750b58..72cdb34714 100644 --- a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php +++ b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php @@ -54,8 +54,7 @@ class MessagingConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - // required for Cloud x Audits - sleep(10); + sleep(10); // required for Cloud x Audits $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ 'content-type' => 'application/json', From 4226e923878802aff19e7fff88c4288aa052d53a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Wed, 8 Jan 2025 13:05:49 +0000 Subject: [PATCH 236/340] Improve DB schema --- app/config/collections.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 7a35dfe356..780870b382 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -5421,7 +5421,7 @@ $consoleCollections = array_merge([ '$id' => ID::custom('personalAccessToken'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 16384, + 'size' => 256, 'signed' => true, 'required' => false, 'default' => null, @@ -5443,7 +5443,7 @@ $consoleCollections = array_merge([ '$id' => ID::custom('personalRefreshToken'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 16384, + 'size' => 256, 'signed' => true, 'required' => false, 'default' => null, From e3637e4ba5bedaf7d9f55dd0e1a34cc55d447eb0 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Wed, 8 Jan 2025 18:40:00 +0530 Subject: [PATCH 237/340] update: lets clear this test too, it has been a while now. --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3ab240c1b9..fc03891b35 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -175,6 +175,8 @@ jobs: name: Benchmark runs-on: ubuntu-latest needs: setup + permissions: + pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v4 From 0daf4057f36b062bd80df21f50d1ebeaf3271d96 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Wed, 8 Jan 2025 19:10:30 +0530 Subject: [PATCH 238/340] fix: benchmark test. --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3ab240c1b9..fc03891b35 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -175,6 +175,8 @@ jobs: name: Benchmark runs-on: ubuntu-latest needs: setup + permissions: + pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v4 From bce68b22028b0699e55ed006114b54bfa2ccbe8d Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Thu, 9 Jan 2025 19:45:03 +0530 Subject: [PATCH 239/340] fix: benchmark test. --- .../Messaging/MessagingConsoleClientTest.php | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php index 72cdb34714..245eb3e8de 100644 --- a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php +++ b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Messaging; +use Appwrite\Tests\Async; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -11,6 +12,8 @@ use Utopia\Database\Query; class MessagingConsoleClientTest extends Scope { + use Async; + use MessagingBase; use ProjectCustom; use SideConsole; @@ -54,17 +57,18 @@ class MessagingConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - sleep(10); // required for Cloud x Audits + // required for Cloud x Audits + $this->assertEventually(function () use ($provider) { + $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); - $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - - $this->assertEquals($logs['headers']['status-code'], 200); - $this->assertIsArray($logs['body']['logs']); - $this->assertIsNumeric($logs['body']['total']); - $this->assertCount(2, $logs['body']['logs']); + $this->assertEquals($logs['headers']['status-code'], 200); + $this->assertIsArray($logs['body']['logs']); + $this->assertIsNumeric($logs['body']['total']); + $this->assertCount(2, $logs['body']['logs']); + }); $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ 'content-type' => 'application/json', From d068067a985e1bafc9eace696cc2c6f75307e852 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:35:40 +0000 Subject: [PATCH 240/340] feat: project sms usage --- app/controllers/api/project.php | 46 ++++++++++++++++++- .../Utopia/Response/Model/MetricBreakdown.php | 8 ++++ .../Utopia/Response/Model/UsageProject.php | 19 ++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 45c8f2c32b..7f3b442727 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -31,7 +31,8 @@ App::get('/v1/project/usage') ->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject) { + ->inject('getSmsPrice') + ->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject, callable $getSmsPrice) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -257,6 +258,46 @@ App::get('/v1/project/usage') ]; }, $dbForProject->find('functions')); + // This total is includes free and paid SMS usage + $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ + Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), + Query::equal('period', ['1d']), + Query::greaterThanEqual('time', $firstDay), + Query::lessThan('time', $lastDay), + ])); + + // This estimate is only for paid SMS usage + $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE . '.'), + Query::equal('period', ['1d']), + Query::greaterThanEqual('time', $firstDay), + Query::lessThan('time', $lastDay), + ])); + + $authPhoneEstimate = 0.0; + $authPhoneCountryBreakdown = []; + foreach ($authPhoneMetrics as $metric) { + $parts = explode('.', $metric->getAttribute('metric')); + $countryCode = $parts[3] ?? null; + if ($countryCode === null) { + continue; + } + + $value = $metric->getAttribute('value', 0); + + if (is_callable($getSmsPrice)) { + $authPhoneEstimate += $value * $getSmsPrice($countryCode); + } + + $authPhoneCountryBreakdown[] = [ + 'name' => $countryCode, + 'value' => $value, + 'estimate' => is_callable($getSmsPrice) + ? $value * $getSmsPrice($countryCode) + : 0.0, + ]; + } + // merge network inbound + outbound $projectBandwidth = []; foreach ($usage[METRIC_NETWORK_INBOUND] as $item) { @@ -303,6 +344,9 @@ App::get('/v1/project/usage') 'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown, 'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown, 'functionsStorageBreakdown' => $functionsStorageBreakdown, + 'authPhoneTotal' => $authPhoneTotal, + 'authPhoneEstimate' => $authPhoneEstimate, + 'authPhoneCountryBreakdown' => $authPhoneCountryBreakdown, ]), Response::MODEL_USAGE_PROJECT); }); diff --git a/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php index 29d5621532..ba46afcb77 100644 --- a/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php +++ b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php @@ -15,6 +15,7 @@ class MetricBreakdown extends Model 'description' => 'Resource ID.', 'default' => '', 'example' => '5e5ea5c16897e', + 'required' => false, ]) ->addRule('name', [ 'type' => self::TYPE_STRING, @@ -27,6 +28,13 @@ class MetricBreakdown extends Model 'description' => 'The value of this metric at the timestamp.', 'default' => 0, 'example' => 1, + ]) + ->addRule('estimate', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'The estimated value of this metric at the end of the period.', + 'default' => 0, + 'example' => 1, + 'required' => false, ]); } diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 17d9271f04..39c245a542 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -152,6 +152,25 @@ class UsageProject extends Model 'example' => [], 'array' => true ]) + ->addRule('authPhoneTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of phone auth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('authPhoneEstimate', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'Estimated total aggregated cost of phone auth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('authPhoneCountryBreakdown', [ + 'type' => Response::MODEL_METRIC_BREAKDOWN, + 'description' => 'Aggregated breakdown in totals of phone auth by country.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } From 651a3d1d622e7ab6dfe3a65ca2e06f1548495773 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:37:26 +0000 Subject: [PATCH 241/340] test: fix --- tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 326443afcf..c21056f727 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -485,6 +485,8 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsNumeric($response['body']['usersTotal']); $this->assertIsNumeric($response['body']['filesStorageTotal']); $this->assertIsNumeric($response['body']['deploymentStorageTotal']); + $this->assertIsNumeric($response['body']['authPhoneTotal']); + $this->assertIsNumeric($response['body']['authPhoneEstimate']); /** From 76e1b27cefb32b64913d4720b96ab8805a500cef Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:41:24 +0000 Subject: [PATCH 242/340] fix: create dummy resource --- app/init.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/init.php b/app/init.php index 51d9c38239..d1749be8f3 100644 --- a/app/init.php +++ b/app/init.php @@ -1844,6 +1844,10 @@ App::setResource('plan', function (array $plan = []) { return []; }); +App::setResource('getSmsPrice', function () { + return []; +}); + App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { $teamInternalId = ''; if ($project->getId() !== 'console') { From 7c9c3d9214cbd044ed09934906f062e9d7ca0054 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:33:07 +0000 Subject: [PATCH 243/340] feat: sms rates --- app/controllers/api/project.php | 12 ++++++------ app/init.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 7f3b442727..d12e35d9d7 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -31,8 +31,8 @@ App::get('/v1/project/usage') ->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true) ->inject('response') ->inject('dbForProject') - ->inject('getSmsPrice') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject, callable $getSmsPrice) { + ->inject('smsRates') + ->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); @@ -285,15 +285,15 @@ App::get('/v1/project/usage') $value = $metric->getAttribute('value', 0); - if (is_callable($getSmsPrice)) { - $authPhoneEstimate += $value * $getSmsPrice($countryCode); + if (!empty($smsRates[$countryCode])) { + $authPhoneEstimate += $value * $smsRates[$countryCode]; } $authPhoneCountryBreakdown[] = [ 'name' => $countryCode, 'value' => $value, - 'estimate' => is_callable($getSmsPrice) - ? $value * $getSmsPrice($countryCode) + 'estimate' => !empty($smsRates[$countryCode]) + ? $value * $smsRates[$countryCode] : 0.0, ]; } diff --git a/app/init.php b/app/init.php index d1749be8f3..acaf3daaca 100644 --- a/app/init.php +++ b/app/init.php @@ -1844,7 +1844,7 @@ App::setResource('plan', function (array $plan = []) { return []; }); -App::setResource('getSmsPrice', function () { +App::setResource('smsRates', function () { return []; }); From ee9e4f90c1586a9f9d78283047312869e028edd8 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:57:00 +0000 Subject: [PATCH 244/340] chore: specs --- app/config/specs/open-api3-1.6.x-client.json | 8 +- app/config/specs/open-api3-1.6.x-console.json | 453 ++++------------- app/config/specs/open-api3-1.6.x-server.json | 104 ++-- .../specs/open-api3-latest-console.json | 36 +- app/config/specs/swagger2-1.6.x-client.json | 8 +- app/config/specs/swagger2-1.6.x-console.json | 469 ++++-------------- app/config/specs/swagger2-1.6.x-server.json | 104 ++-- app/config/specs/swagger2-latest-console.json | 37 +- 8 files changed, 378 insertions(+), 841 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 e3cd909b4e..af7303c985 100644 --- a/app/config/specs/open-api3-1.6.x-client.json +++ b/app/config/specs/open-api3-1.6.x-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2784,7 +2784,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -5766,7 +5766,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -5851,7 +5851,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, 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 369fea741a..5b0e5376f5 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2795,7 +2795,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -9488,7 +9488,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10145,7 +10146,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13673,7 +13675,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13751,7 +13753,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -13897,7 +13899,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -14045,7 +14047,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14202,7 +14204,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14361,7 +14363,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14472,7 +14474,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -14586,7 +14588,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14641,7 +14643,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14705,7 +14707,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -14782,7 +14784,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -14859,7 +14861,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14937,7 +14939,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -15044,7 +15046,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15154,7 +15156,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15241,7 +15243,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15331,7 +15333,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15448,7 +15450,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15568,7 +15570,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15665,7 +15667,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15765,7 +15767,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -15872,7 +15874,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15982,7 +15984,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16127,7 +16129,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16274,7 +16276,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16371,7 +16373,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16471,7 +16473,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16568,7 +16570,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -16668,7 +16670,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16765,7 +16767,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16865,7 +16867,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16962,7 +16964,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -17062,7 +17064,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17117,7 +17119,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17181,7 +17183,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17258,7 +17260,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17335,7 +17337,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17411,7 +17413,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17496,7 +17498,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17558,7 +17560,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -17637,7 +17639,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -17701,7 +17703,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17778,7 +17780,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17864,7 +17866,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17956,7 +17958,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -18021,7 +18023,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18098,7 +18100,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18264,7 +18266,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18339,7 +18341,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "tags": [ "migrations" @@ -18359,7 +18361,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18415,177 +18417,6 @@ } } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File" - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migration" - } - } - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-migration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "requestBody": { - "content": { - "application\/json": { - "schema": { - "type": "object", - "properties": { - "resources": { - "type": "array", - "description": "List of resources to migrate", - "x-example": null, - "items": { - "type": "string" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - } - } - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/firebaseProjectList" - } - } - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -18608,7 +18439,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -18660,80 +18491,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migrationReport" - } - } - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "schema": { - "type": "string", - "x-example": "<PROJECT_ID>" - }, - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -18756,7 +18513,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -18869,7 +18626,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -19004,7 +18761,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19111,7 +18868,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19237,7 +18994,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19297,7 +19054,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19350,7 +19107,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -32749,30 +32506,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase Projects List", - "type": "object", - "properties": { - "total": { - "type": "integer", - "description": "Total number of projects documents that matched your query.", - "x-example": 5, - "format": "int32" - }, - "projects": { - "type": "array", - "description": "List of projects.", - "items": { - "$ref": "#\/components\/schemas\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35109,7 +34842,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -36976,7 +36709,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "nullable": true }, "name": { "type": "string", @@ -36988,10 +36722,16 @@ "description": "The value of this metric at the timestamp.", "x-example": 1, "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "nullable": true } }, "required": [ - "resourceId", "name", "value" ] @@ -37807,6 +37547,26 @@ "$ref": "#\/components\/schemas\/metricBreakdown" }, "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] } }, "required": [ @@ -37831,7 +37591,10 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown" ] }, "headers": { @@ -38707,26 +38470,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "securitySchemes": { 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 e84b751743..8900d6ddf2 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2451,7 +2451,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -8596,7 +8596,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9019,7 +9020,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12527,7 +12529,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12606,7 +12608,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12753,7 +12755,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -12902,7 +12904,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -13060,7 +13062,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13220,7 +13222,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13332,7 +13334,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -13447,7 +13449,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13503,7 +13505,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13568,7 +13570,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13646,7 +13648,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -13724,7 +13726,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -13803,7 +13805,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13911,7 +13913,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14022,7 +14024,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14110,7 +14112,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14201,7 +14203,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14319,7 +14321,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14440,7 +14442,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14538,7 +14540,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14639,7 +14641,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -14747,7 +14749,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14858,7 +14860,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15004,7 +15006,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15152,7 +15154,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15250,7 +15252,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15351,7 +15353,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15449,7 +15451,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15550,7 +15552,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -15648,7 +15650,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15749,7 +15751,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -15847,7 +15849,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -15948,7 +15950,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -16004,7 +16006,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16069,7 +16071,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16147,7 +16149,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16225,7 +16227,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16302,7 +16304,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16388,7 +16390,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16451,7 +16453,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16531,7 +16533,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -16596,7 +16598,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -16674,7 +16676,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -16761,7 +16763,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -16855,7 +16857,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -16921,7 +16923,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -25746,7 +25748,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 6878909f64..5b0e5376f5 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -36709,7 +36709,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "nullable": true }, "name": { "type": "string", @@ -36721,10 +36722,16 @@ "description": "The value of this metric at the timestamp.", "x-example": 1, "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "nullable": true } }, "required": [ - "resourceId", "name", "value" ] @@ -37540,6 +37547,26 @@ "$ref": "#\/components\/schemas\/metricBreakdown" }, "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] } }, "required": [ @@ -37564,7 +37591,10 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown" ] }, "headers": { diff --git a/app/config/specs/swagger2-1.6.x-client.json b/app/config/specs/swagger2-1.6.x-client.json index b1b9ce8dca..77025ec042 100644 --- a/app/config/specs/swagger2-1.6.x-client.json +++ b/app/config/specs/swagger2-1.6.x-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2922,7 +2922,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -5981,7 +5981,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -6070,7 +6070,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index 9ce9d5f60d..d5c82bba49 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2949,7 +2949,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -9610,7 +9610,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10286,7 +10287,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -13890,7 +13892,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13967,7 +13969,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -14127,7 +14129,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -14284,7 +14286,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14459,7 +14461,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14631,7 +14633,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14751,7 +14753,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -14869,7 +14871,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14928,7 +14930,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14992,7 +14994,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -15068,7 +15070,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -15144,7 +15146,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -15221,7 +15223,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -15338,7 +15340,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15453,7 +15455,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15546,7 +15548,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15637,7 +15639,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15766,7 +15768,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15893,7 +15895,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15998,7 +16000,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -16101,7 +16103,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16218,7 +16220,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -16333,7 +16335,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16494,7 +16496,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16652,7 +16654,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16757,7 +16759,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16860,7 +16862,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16965,7 +16967,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -17068,7 +17070,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17173,7 +17175,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -17276,7 +17278,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17381,7 +17383,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -17484,7 +17486,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17543,7 +17545,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17607,7 +17609,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17683,7 +17685,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17759,7 +17761,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17834,7 +17836,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17926,7 +17928,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17988,7 +17990,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -18071,7 +18073,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -18135,7 +18137,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -18211,7 +18213,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -18294,7 +18296,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -18386,7 +18388,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -18453,7 +18455,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18528,7 +18530,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18699,7 +18701,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18767,7 +18769,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "consumes": [ "application\/json" @@ -18789,7 +18791,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18847,192 +18849,6 @@ ] } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File", - "schema": { - "type": "file" - } - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "schema": { - "$ref": "#\/definitions\/migration" - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-migration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "payload", - "in": "body", - "schema": { - "type": "object", - "properties": { - "resources": { - "type": "array", - "description": "List of resources to migrate", - "default": null, - "x-example": null, - "items": { - "type": "string" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "default": null, - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - ] - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "schema": { - "$ref": "#\/definitions\/firebaseProjectList" - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -19057,7 +18873,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -19106,79 +18922,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "schema": { - "$ref": "#\/definitions\/migrationReport" - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "type": "array", - "collectionFormat": "multi", - "items": { - "type": "string" - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "type": "string", - "x-example": "<PROJECT_ID>", - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -19203,7 +18946,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -19326,7 +19069,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -19448,7 +19191,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19564,7 +19307,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19679,7 +19422,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19739,7 +19482,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19794,7 +19537,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -33250,31 +32993,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase Projects List", - "type": "object", - "properties": { - "total": { - "type": "integer", - "description": "Total number of projects documents that matched your query.", - "x-example": 5, - "format": "int32" - }, - "projects": { - "type": "array", - "description": "List of projects.", - "items": { - "type": "object", - "$ref": "#\/definitions\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35618,7 +35336,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -37494,7 +37212,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "x-nullable": true }, "name": { "type": "string", @@ -37506,10 +37225,16 @@ "description": "The value of this metric at the timestamp.", "x-example": 1, "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "x-nullable": true } }, "required": [ - "resourceId", "name", "value" ] @@ -38369,6 +38094,27 @@ "$ref": "#\/definitions\/metricBreakdown" }, "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] } }, "required": [ @@ -38393,7 +38139,10 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown" ] }, "headers": { @@ -39274,26 +39023,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "externalDocs": { diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 2c8e80c65e..f5b1f24a22 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "title": "Appwrite", "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)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -2604,7 +2604,7 @@ "tags": [ "account" ], - "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", "responses": { "201": { "description": "Token", @@ -8720,7 +8720,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9166,7 +9167,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -12752,7 +12754,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12830,7 +12832,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12991,7 +12993,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -13149,7 +13151,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -13325,7 +13327,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13498,7 +13500,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13619,7 +13621,7 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -13738,7 +13740,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13798,7 +13800,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13863,7 +13865,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13940,7 +13942,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -14017,7 +14019,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14095,7 +14097,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14213,7 +14215,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14329,7 +14331,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14423,7 +14425,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14515,7 +14517,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14645,7 +14647,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14773,7 +14775,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14879,7 +14881,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14983,7 +14985,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -15101,7 +15103,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15217,7 +15219,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15379,7 +15381,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15538,7 +15540,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15644,7 +15646,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15748,7 +15750,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15854,7 +15856,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15958,7 +15960,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16064,7 +16066,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16168,7 +16170,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16274,7 +16276,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -16378,7 +16380,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -16438,7 +16440,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16503,7 +16505,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16580,7 +16582,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16657,7 +16659,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16733,7 +16735,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16826,7 +16828,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16889,7 +16891,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16973,7 +16975,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -17038,7 +17040,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17115,7 +17117,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17199,7 +17201,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17293,7 +17295,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -17361,7 +17363,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -26233,7 +26235,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 0ef937050c..d5c82bba49 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -37212,7 +37212,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "x-nullable": true }, "name": { "type": "string", @@ -37224,10 +37225,16 @@ "description": "The value of this metric at the timestamp.", "x-example": 1, "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "x-nullable": true } }, "required": [ - "resourceId", "name", "value" ] @@ -38087,6 +38094,27 @@ "$ref": "#\/definitions\/metricBreakdown" }, "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] } }, "required": [ @@ -38111,7 +38139,10 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown" ] }, "headers": { From cc7cef59b344e094c047a95131a06910d6b7c917 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:03:25 +0000 Subject: [PATCH 245/340] isset over empty --- app/controllers/api/project.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index d12e35d9d7..7e704762b8 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -285,14 +285,14 @@ App::get('/v1/project/usage') $value = $metric->getAttribute('value', 0); - if (!empty($smsRates[$countryCode])) { + if (isset($smsRates[$countryCode])) { $authPhoneEstimate += $value * $smsRates[$countryCode]; } $authPhoneCountryBreakdown[] = [ 'name' => $countryCode, 'value' => $value, - 'estimate' => !empty($smsRates[$countryCode]) + 'estimate' => isset($smsRates[$countryCode]) ? $value * $smsRates[$countryCode] : 0.0, ]; From a85abdab4af4735f2215e1d55eed2cb0cc7494d6 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:11:02 +0000 Subject: [PATCH 246/340] fix: usage tests --- tests/e2e/General/UsageTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index c50a15fd3f..7263a2eee1 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -143,7 +143,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(25, count($response['body'])); $this->validateDates($response['body']['network']); $this->validateDates($response['body']['requests']); $this->validateDates($response['body']['users']); From ec7f76f9fb640421dcfc6becdd0672e66ae531e3 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 9 Jan 2025 21:17:53 +0000 Subject: [PATCH 247/340] fix: stats tests --- tests/e2e/General/UsageTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 7263a2eee1..f6b2ca4882 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -324,7 +324,7 @@ class UsageTest extends Scope ] ); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(25, count($response['body'])); $this->assertEquals(1, count($response['body']['requests'])); $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); $this->validateDates($response['body']['requests']); @@ -545,7 +545,7 @@ class UsageTest extends Scope ] ); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(25, count($response['body'])); $this->assertEquals(1, count($response['body']['requests'])); $this->assertEquals(1, count($response['body']['network'])); $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); From d86984f6cf5ab936ad26075a4c7e7fa43745d83e Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Fri, 10 Jan 2025 08:42:10 +0530 Subject: [PATCH 248/340] chore: used config in auth --- app/controllers/api/account.php | 4 ++-- app/controllers/shared/api/auth.php | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index ff96acfc57..6935029450 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -278,7 +278,7 @@ App::post('/v1/account') ->desc('Create account') ->groups(['api', 'account', 'auth']) ->label('scope', 'sessions.write') - ->label('auth.type', 'emailPassword') + ->label('auth.type', 'email-password') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') @@ -799,7 +799,7 @@ App::post('/v1/account/sessions/email') ->groups(['api', 'account', 'auth', 'session']) ->label('event', 'users.[userId].sessions.[sessionId].create') ->label('scope', 'sessions.write') - ->label('auth.type', 'emailPassword') + ->label('auth.type', 'email-password') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index 53aacabe21..ecabc641ec 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -5,6 +5,7 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use Utopia\App; +use Utopia\Config\Config; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; @@ -57,44 +58,44 @@ App::init() $auths = $project->getAttribute('auths', []); switch ($route->getLabel('auth.type', '')) { - case 'emailPassword': - if (($auths['emailPassword'] ?? true) === false) { + case 'email-password': + if (($auths[Config::getParam('auth')['email-password']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email / Password authentication is disabled for this project'); } break; case 'magic-url': - if (($auths['usersAuthMagicURL'] ?? true) === false) { + if (($auths[Config::getParam('auth')['magic-url']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Magic URL authentication is disabled for this project'); } break; case 'anonymous': - if (($auths['anonymous'] ?? true) === false) { + if (($auths[Config::getParam('auth')['anonymous']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Anonymous authentication is disabled for this project'); } break; case 'phone': - if (($auths['phone'] ?? true) === false) { + if (($auths[Config::getParam('auth')['phone']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Phone authentication is disabled for this project'); } break; case 'invites': - if (($auths['invites'] ?? true) === false) { + if (($auths[Config::getParam('auth')['invites']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Invites authentication is disabled for this project'); } break; case 'jwt': - if (($auths['JWT'] ?? true) === false) { + if (($auths[Config::getParam('auth')['jwt']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'JWT authentication is disabled for this project'); } break; case 'email-otp': - if (($auths['emailOTP'] ?? true) === false) { + if (($auths[Config::getParam('auth')['email-otp']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email OTP authentication is disabled for this project'); } break; From b88d9c51fb374c1cc4faa35f178cda3dcd27fd20 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Fri, 10 Jan 2025 20:19:34 +1300 Subject: [PATCH 249/340] Revert "Fix dead connections" --- app/controllers/general.php | 14 +---------- app/http.php | 11 -------- app/init.php | 31 ++++++----------------- app/worker.php | 50 ++++++++++++++----------------------- composer.json | 2 +- composer.lock | 38 ++++++++++++++-------------- 6 files changed, 48 insertions(+), 98 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 90cb3293e6..db9df71341 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -21,7 +21,6 @@ use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; -use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Utopia\App; use Utopia\CLI\Console; @@ -29,7 +28,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -40,7 +38,6 @@ use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Logger\Logger; -use Utopia\Pools\Connection; use Utopia\System\System; use Utopia\Validator\Hostname; use Utopia\Validator\Text; @@ -749,16 +746,7 @@ App::error() ->inject('logger') ->inject('log') ->inject('queueForUsage') - ->inject('connectionForProject') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage, Connection $connectionForProject) { - if ( - ($error instanceof PDOException || $error instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($error) - ) { - // Mark connection as unhealthy so it will be recycled on next reclaim. - $connectionForProject->setHealthy(false); - } - + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); diff --git a/app/http.php b/app/http.php index b988c7d8ac..3a7562ffd1 100644 --- a/app/http.php +++ b/app/http.php @@ -5,7 +5,6 @@ require_once __DIR__ . '/../vendor/autoload.php'; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Constant; -use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; @@ -18,7 +17,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -348,15 +346,6 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $app->run($request, $response); } catch (\Throwable $th) { - if ( - ($th instanceof PDOException || $th instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($th) - ) { - // Mark connection as unhealthy so it will be recycled on next reclaim. - $connectionForProject = $app->getResource('connectionForProject'); - $connectionForProject->setHealthy(false); - } - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $logger = $app->getResource("logger"); diff --git a/app/init.php b/app/init.php index 51d9c38239..b4e60d7924 100644 --- a/app/init.php +++ b/app/init.php @@ -74,7 +74,6 @@ use Utopia\Logger\Adapter\Raygun; use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Logger; -use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Pools\Pool; use Utopia\Queue; @@ -1413,26 +1412,7 @@ App::setResource('console', function () { ]); }, []); -App::setResource('connectionForProject', function (Group $pools, Document $project) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $pools - ->get('console') - ->pop(); - } - - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - - return $pools - ->get($dsn->getHost()) - ->pop(); -}, ['pools', 'project']); - -App::setResource('dbForProject', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -1444,7 +1424,12 @@ App::setResource('dbForProject', function (Group $pools, PoolConnection $connect $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $database = new Database($connectionForProject->getResource(), $cache); + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); $database ->setMetadata('host', \gethostname()) @@ -1467,7 +1452,7 @@ App::setResource('dbForProject', function (Group $pools, PoolConnection $connect } return $database; -}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $dbAdapter = $pools diff --git a/app/worker.php b/app/worker.php index 62882b32b1..6eb1363e9b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -16,7 +16,6 @@ use Appwrite\Event\Migration; use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; -use Swoole\Database\DetectsLostConnections; use Swoole\Runtime; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; @@ -26,13 +25,11 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; -use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Queue\Connection; use Utopia\Queue\Message; @@ -69,13 +66,13 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('connectionForProject', function (Group $pools, Document $project) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { - return $pools - ->get('console') - ->pop(); + return $dbForPlatform; } + $pools = $register->get('pools'); + try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -83,17 +80,12 @@ Server::setResource('connectionForProject', function (Group $pools, Document $pr $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - return $pools + $adapter = $pools ->get($dsn->getHost()) - ->pop(); -}, ['pools', 'project']); + ->pop() + ->getResource(); -Server::setResource('dbForProject', function (PoolConnection $connectionForProject, Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForPlatform; - } - - $database = new Database($connectionForProject->getResource(), $cache); + $database = new Database($adapter, $cache); try { $dsn = new DSN($project->getAttribute('database')); @@ -117,12 +109,12 @@ Server::setResource('dbForProject', function (PoolConnection $connectionForProje } return $database; -}, ['connectionForProject', 'cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $connectionForProject, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -154,7 +146,12 @@ Server::setResource('getProjectDB', function (Group $pools, PoolConnection $conn return $database; } - $database = new Database($connectionForProject->getResource(), $cache); + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); $databases[$dsn->getHost()] = $database; @@ -174,7 +171,7 @@ Server::setResource('getProjectDB', function (Group $pools, PoolConnection $conn return $database; }; -}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); @@ -413,16 +410,7 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->inject('connectionForProject') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, PoolConnection $connectionForProject) use ($queueName) { - if ( - ($error instanceof PDOException || $error instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($error) - ) { - // Mark connection as unhealthy, it will be recycled on next reclaim. - $connectionForProject->setHealthy(false); - } - + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) { $pools->reclaim(); $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); diff --git a/composer.json b/composer.json index 2612403c1a..e44dd0bffc 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.6.*", + "utopia-php/pools": "0.5.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index 045ef31ffa..b906af3a81 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": "7b5b5926b452186543903eb539f59c2d", + "content-hash": "6b136b5490c0d5d331eac0d70bb3e198", "packages": [ { "name": "adhocore/jwt", @@ -3929,16 +3929,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.14", + "version": "0.6.13", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2" + "reference": "68d9b0a9477755afcda607e7e8109785cae17a13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/68d9b0a9477755afcda607e7e8109785cae17a13", + "reference": "68d9b0a9477755afcda607e7e8109785cae17a13", "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.14" + "source": "https://github.com/utopia-php/migration/tree/0.6.13" }, - "time": "2025-01-08T01:07:25+00:00" + "time": "2024-11-26T13:57:53+00:00" }, { "name": "utopia-php/mongo", @@ -4145,25 +4145,25 @@ }, { "name": "utopia-php/pools", - "version": "0.6.0", + "version": "0.5.0", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18" + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/59414ab7b57728edfde6d5ccc5a2583b7967ac18", - "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.0" }, "require-dev": { - "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", - "phpunit/phpunit": "11.*" + "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.8.*", + "phpunit/phpunit": "^9.3" }, "type": "library", "autoload": { @@ -4190,9 +4190,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.6.0" + "source": "https://github.com/utopia-php/pools/tree/0.5.0" }, - "time": "2025-01-08T07:58:42+00:00" + "time": "2024-04-19T11:11:54+00:00" }, { "name": "utopia-php/preloader", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8580,5 +8580,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } From b76260ecce1f8e9f14c9f07a037052c9cfdf34fc Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Fri, 10 Jan 2025 20:28:50 +1300 Subject: [PATCH 250/340] Update database --- composer.json | 4 +-- composer.lock | 84 +++++++++++++++++++++++++-------------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/composer.json b/composer.json index 2612403c1a..90edca6485 100644 --- a/composer.json +++ b/composer.json @@ -45,13 +45,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.46.*", + "utopia-php/abuse": "0.43.*", "utopia-php/analytics": "0.10.*", "utopia-php/audit": "0.43.*", "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.200", + "utopia-php/database": "0.53.31", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 045ef31ffa..b8e02a8b65 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": "7b5b5926b452186543903eb539f59c2d", + "content-hash": "0cd8b051f3b6e11f9c537ccfe6b166d1", "packages": [ { "name": "adhocore/jwt", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.29.2", + "version": "v4.29.3", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945" + "reference": "ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/79aa5014efeeec3d137df5cdb0ae2fc163953945", - "reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945", + "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.2" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.3" }, - "time": "2024-12-18T14:11:12+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.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" + "reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", - "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/351a30baa79699de3de3a814c8ccc7b52ccdfb1d", + "reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d", "shasum": "" }, "require": { @@ -1303,7 +1303,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-11-16T04:32:30+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": { @@ -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", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.46.0", + "version": "0.43.3", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "bef426a9a28b3e71b08216bcbe310455f588c11b" + "reference": "c8a403bd79694c9790e3023e0a84c6e350ae0f2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/bef426a9a28b3e71b08216bcbe310455f588c11b", - "reference": "bef426a9a28b3e71b08216bcbe310455f588c11b", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/c8a403bd79694c9790e3023e0a84c6e350ae0f2a", + "reference": "c8a403bd79694c9790e3023e0a84c6e350ae0f2a", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.200" + "utopia-php/database": "0.53.31" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.46.0" + "source": "https://github.com/utopia-php/abuse/tree/0.43.3" }, - "time": "2024-12-27T17:46:08+00:00" + "time": "2025-01-10T07:26:06+00:00" }, { "name": "utopia-php/analytics", @@ -3233,21 +3233,21 @@ }, { "name": "utopia-php/audit", - "version": "0.43.1", + "version": "0.43.3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277" + "reference": "1fef1d5163e114d3bd357cf4bc0cb8d0482faf53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/04a47dd1f5f92e2d50e971a06bcc9e759325d277", - "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1fef1d5163e114d3bd357cf4bc0cb8d0482faf53", + "reference": "1fef1d5163e114d3bd357cf4bc0cb8d0482faf53", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.53.31" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3274,9 +3274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.43.1" + "source": "https://github.com/utopia-php/audit/tree/0.43.3" }, - "time": "2024-10-23T04:27:59+00:00" + "time": "2025-01-10T07:23:31+00:00" }, { "name": "utopia-php/cache", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.200", + "version": "0.53.31", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc" + "reference": "874f2fa096c85a224fa1cdabea74760a7d7aac0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/570c63a3760d0e1404679ddfacd9484af40bd9fc", - "reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc", + "url": "https://api.github.com/repos/utopia-php/database/zipball/874f2fa096c85a224fa1cdabea74760a7d7aac0c", + "reference": "874f2fa096c85a224fa1cdabea74760a7d7aac0c", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.200" + "source": "https://github.com/utopia-php/database/tree/0.53.31" }, - "time": "2024-12-01T07:59:15+00:00" + "time": "2025-01-10T06:51:16+00:00" }, { "name": "utopia-php/domains", From a45e0a59dd968ea566555e97873d539c2ebbf338 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Fri, 10 Jan 2025 22:05:40 +1300 Subject: [PATCH 251/340] Update database --- app/init.php | 2 +- app/realtime.php | 2 +- app/worker.php | 2 +- composer.json | 2 +- composer.lock | 42 +++++++++++++++++++++--------------------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/init.php b/app/init.php index 51d9c38239..1da4771d1d 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,7 @@ use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use PHPMailer\PHPMailer\PHPMailer; use Swoole\Database\PDOProxy; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Adapter\Sharding; diff --git a/app/realtime.php b/app/realtime.php index 86f9c85fdd..3c543ee166 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; diff --git a/app/worker.php b/app/worker.php index 62882b32b1..50249ed605 100644 --- a/app/worker.php +++ b/app/worker.php @@ -18,7 +18,7 @@ use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Database\DetectsLostConnections; use Swoole\Runtime; -use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; diff --git a/composer.json b/composer.json index 90edca6485..e21c4abe84 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.31", + "utopia-php/database": "0.53.32", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index b8e02a8b65..6dec3249da 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": "0cd8b051f3b6e11f9c537ccfe6b166d1", + "content-hash": "6f80de1fcc781dfbf379e6898a4f57ab", "packages": [ { "name": "adhocore/jwt", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.3", + "version": "0.43.4", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "c8a403bd79694c9790e3023e0a84c6e350ae0f2a" + "reference": "2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/c8a403bd79694c9790e3023e0a84c6e350ae0f2a", - "reference": "c8a403bd79694c9790e3023e0a84c6e350ae0f2a", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9", + "reference": "2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.31" + "utopia-php/database": "0.53.32" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.3" + "source": "https://github.com/utopia-php/abuse/tree/0.43.4" }, - "time": "2025-01-10T07:26:06+00:00" + "time": "2025-01-10T08:58:29+00:00" }, { "name": "utopia-php/analytics", @@ -3233,21 +3233,21 @@ }, { "name": "utopia-php/audit", - "version": "0.43.3", + "version": "0.43.4", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "1fef1d5163e114d3bd357cf4bc0cb8d0482faf53" + "reference": "d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/1fef1d5163e114d3bd357cf4bc0cb8d0482faf53", - "reference": "1fef1d5163e114d3bd357cf4bc0cb8d0482faf53", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7", + "reference": "d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.53.31" + "utopia-php/database": "0.53.32" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3274,9 +3274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.43.3" + "source": "https://github.com/utopia-php/audit/tree/0.43.4" }, - "time": "2025-01-10T07:23:31+00:00" + "time": "2025-01-10T08:57:54+00:00" }, { "name": "utopia-php/cache", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.31", + "version": "0.53.32", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "874f2fa096c85a224fa1cdabea74760a7d7aac0c" + "reference": "981a1241139b42dccd531511130b79137740b205" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/874f2fa096c85a224fa1cdabea74760a7d7aac0c", - "reference": "874f2fa096c85a224fa1cdabea74760a7d7aac0c", + "url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205", + "reference": "981a1241139b42dccd531511130b79137740b205", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.31" + "source": "https://github.com/utopia-php/database/tree/0.53.32" }, - "time": "2025-01-10T06:51:16+00:00" + "time": "2025-01-10T08:53:47+00:00" }, { "name": "utopia-php/domains", From 428efdede02d39cf1313ec4892246fb46d0521d9 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Fri, 10 Jan 2025 22:32:25 +1300 Subject: [PATCH 252/340] Update lock --- composer.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.lock b/composer.lock index fe3331bd4a..13c76ab59a 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": "6f80de1fcc781dfbf379e6898a4f57ab", + "content-hash": "630e10509c6effad82583cd67ad49974", "packages": [ { "name": "adhocore/jwt", @@ -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", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8580,5 +8580,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } From 1695e90399531634bd95802fea5a019a76d03f7b Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:33:08 +0000 Subject: [PATCH 253/340] fix: metric --- app/controllers/api/project.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 7e704762b8..5a1bf063f2 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -268,7 +268,7 @@ App::get('/v1/project/usage') // This estimate is only for paid SMS usage $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ - Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE . '.'), + Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), Query::lessThan('time', $lastDay), From 4fe2611cccd68dce86550b071d78acf69c02027c Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Sat, 11 Jan 2025 11:07:10 +0530 Subject: [PATCH 254/340] add: missing scope to template to prevent a crash on console. --- app/config/function-templates.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/config/function-templates.php b/app/config/function-templates.php index fec9d2227f..4bd8b83f4d 100644 --- a/app/config/function-templates.php +++ b/app/config/function-templates.php @@ -1567,7 +1567,8 @@ return [ 'required' => false, 'type' => 'number' ] - ] + ], + 'scopes' => [] ], [ 'icon' => 'icon-chip', From f48c843bea10e77fd5704b47b85d4488f1b12b27 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:56:36 +0000 Subject: [PATCH 255/340] fix(users): ensure user can delete session The session document created by users.createSession() was missing delete permissions for the user so when the user tried to delete it, they got a 401 error. This PR ensure the permissions are added just like if the document was created from the Account API so that the user has access to delete the document. --- app/controllers/api/users.php | 6 ++++++ tests/e2e/Services/Users/UsersBase.php | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bdb24572eb..9fe7f433c9 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1814,6 +1814,12 @@ App::post('/v1/users/:userId/sessions') $detector->getDevice() )); + $session->setAttribute('$permissions', [ + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ]); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session = $dbForProject->createDocument('sessions', $session); diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index bbf9a5e2df..04e0eb5bc3 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -318,6 +318,14 @@ trait UsersBase ]); $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-session' => $session['secret'] + ]); + + $this->assertEquals(204, $response['headers']['status-code']); } From 1e62e26ef1673e8855d0aae7baf7d811e6a431f3 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Sun, 12 Jan 2025 12:42:52 +0530 Subject: [PATCH 256/340] add: `userType` and `keyName` to Audits. --- app/controllers/shared/api.php | 17 +++++++--- app/init.php | 40 ++++++++++++++++++++++++ src/Appwrite/Platform/Workers/Audits.php | 2 ++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 182151a6c3..33adb428cb 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -659,6 +659,7 @@ App::shutdown() ->inject('response') ->inject('project') ->inject('user') + ->inject('userType') ->inject('queueForEvents') ->inject('queueForAudits') ->inject('queueForUsage') @@ -670,7 +671,7 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Document $userType, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -708,11 +709,17 @@ App::shutdown() } } - if (!$user->isEmpty()) { - $queueForAudits->setUser($user); - } + $localUserInstance = clone $user; + $localUserInstance->setAttributes([ + 'keyName' => $userType->getAttribute('key'), + 'userType' => $userType->getAttribute('type', 'user'), + ]); - if (!empty($queueForAudits->getResource()) && !empty($queueForAudits->getUser()->getId())) { + // even if the user is empty, + // set the available info when using API Key. + $queueForAudits->setUser($localUserInstance); + + if (!empty($queueForAudits->getResource())) { /** * audits.payload is switched to default true * in order to auto audit payload for all endpoints diff --git a/app/init.php b/app/init.php index 0a241813b5..43a5526f9e 100644 --- a/app/init.php +++ b/app/init.php @@ -1349,6 +1349,46 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $project; }, ['dbForPlatform', 'request', 'console']); +App::setResource('userType', function ($request, $project, $user) { + /** @var Appwrite\Utopia\Request $request */ + /** @var Utopia\Database\Document $project */ + /** @var Utopia\Database\Document $user */ + + $userType = new Document(); + $apiKey = $request->getHeader('x-appwrite-key', ''); + + // Case 1: User exists, no API key + if (!$user->isEmpty() && empty($apiKey)) { + $userType + ->setAttribute('key', null) + ->setAttribute('type', 'user'); + return $userType; + } + + // Case 2: API key exists, user is empty + if (!empty($apiKey) && $user->isEmpty()) { + $userType->setAttribute('type', 'app'); + + // covers both legacy and new format. + $keyType = \str_contains($apiKey, '_') + ? \explode('_', $apiKey, 2)[0] + : API_KEY_STANDARD; + + switch ($keyType) { + case API_KEY_STANDARD: + $key = $project->find('secret', $apiKey, 'keys'); + $userType->setAttribute('key', $key ? $key->getAttribute('name', 'UNKNOWN') : 'UNKNOWN'); + break; + + case API_KEY_DYNAMIC: + $userType->setAttribute('key', 'dynamic'); + break; + } + } + + return $userType; +}, ['request', 'project', 'user']); + App::setResource('session', function (Document $user) { if ($user->isEmpty()) { return; diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 86ca59d3fd..f2825abddf 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -76,6 +76,8 @@ class Audits extends Action 'userEmail' => $userEmail, 'mode' => $mode, 'data' => $auditPayload, + 'keyName' => $user->getAttribute('keyName'), + 'userType' => $user->getAttribute('userType'), ] ); } From e237f7c05d8994863bc06a35010628a9ed97c30b Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Sun, 12 Jan 2025 16:58:38 +0530 Subject: [PATCH 257/340] address comments: make things less complex. --- app/controllers/shared/api.php | 42 ++++++++++++++---------- app/init.php | 40 ---------------------- src/Appwrite/Auth/Auth.php | 6 ++++ src/Appwrite/Platform/Workers/Audits.php | 2 -- 4 files changed, 31 insertions(+), 59 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 33adb428cb..dfb491594d 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -185,13 +185,14 @@ App::init() ->inject('request') ->inject('dbForPlatform') ->inject('dbForProject') + ->inject('queueForAudits') ->inject('project') ->inject('user') ->inject('session') ->inject('servers') ->inject('mode') ->inject('team') - ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) { + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) { $route = $utopia->getRoute(); if ($project->isEmpty()) { @@ -243,9 +244,10 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, + 'type' => Auth::AUDIT_TYPE_APP, 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', - 'name' => $project->getAttribute('name', 'Untitled'), + 'name' => 'Dynamic Key', ]); $role = Auth::USER_ROLE_APPS; @@ -253,6 +255,9 @@ App::init() Authorization::setRole(Auth::USER_ROLE_APPS); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. + + // dynamic api key user + $queueForAudits->setUser($user); } } elseif ($keyType === API_KEY_STANDARD) { // No underline means no prefix. Backwards compatibility. @@ -264,9 +269,10 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, + 'type' => Auth::AUDIT_TYPE_APP, 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', - 'name' => $project->getAttribute('name', 'Untitled'), + 'name' => $key->getAttribute('name', 'UNKNOWN'), ]); $role = Auth::USER_ROLE_APPS; @@ -301,6 +307,8 @@ App::init() $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } + + $queueForAudits->setUser($user); } } } @@ -508,8 +516,14 @@ App::init() ->setIP($request->getIP()) ->setHostname($request->getHostname()) ->setEvent($route->getLabel('audits.event', '')) - ->setProject($project) - ->setUser($user); + ->setProject($project); + + // check first, + // as api key user might already exists + if (!$user->isEmpty()) { + $user->setAttribute('type', Auth::AUDIT_TYPE_USER); + $queueForAudits->setUser($user); + } $queueForDeletes->setProject($project); $queueForDatabase->setProject($project); @@ -659,7 +673,6 @@ App::shutdown() ->inject('response') ->inject('project') ->inject('user') - ->inject('userType') ->inject('queueForEvents') ->inject('queueForAudits') ->inject('queueForUsage') @@ -671,7 +684,7 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Document $userType, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -709,17 +722,12 @@ App::shutdown() } } - $localUserInstance = clone $user; - $localUserInstance->setAttributes([ - 'keyName' => $userType->getAttribute('key'), - 'userType' => $userType->getAttribute('type', 'user'), - ]); + if (!$user->isEmpty()) { + $user->setAttribute('type', Auth::AUDIT_TYPE_USER); + $queueForAudits->setUser($user); + } - // even if the user is empty, - // set the available info when using API Key. - $queueForAudits->setUser($localUserInstance); - - if (!empty($queueForAudits->getResource())) { + if (!empty($queueForAudits->getResource()) && !$queueForAudits->getUser()->isEmpty()) { /** * audits.payload is switched to default true * in order to auto audit payload for all endpoints diff --git a/app/init.php b/app/init.php index 43a5526f9e..0a241813b5 100644 --- a/app/init.php +++ b/app/init.php @@ -1349,46 +1349,6 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $project; }, ['dbForPlatform', 'request', 'console']); -App::setResource('userType', function ($request, $project, $user) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Document $user */ - - $userType = new Document(); - $apiKey = $request->getHeader('x-appwrite-key', ''); - - // Case 1: User exists, no API key - if (!$user->isEmpty() && empty($apiKey)) { - $userType - ->setAttribute('key', null) - ->setAttribute('type', 'user'); - return $userType; - } - - // Case 2: API key exists, user is empty - if (!empty($apiKey) && $user->isEmpty()) { - $userType->setAttribute('type', 'app'); - - // covers both legacy and new format. - $keyType = \str_contains($apiKey, '_') - ? \explode('_', $apiKey, 2)[0] - : API_KEY_STANDARD; - - switch ($keyType) { - case API_KEY_STANDARD: - $key = $project->find('secret', $apiKey, 'keys'); - $userType->setAttribute('key', $key ? $key->getAttribute('name', 'UNKNOWN') : 'UNKNOWN'); - break; - - case API_KEY_DYNAMIC: - $userType->setAttribute('key', 'dynamic'); - break; - } - } - - return $userType; -}, ['request', 'project', 'user']); - App::setResource('session', function (Document $user) { if ($user->isEmpty()) { return; diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 1e8109622e..a2bb2dea1c 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -43,6 +43,12 @@ class Auth public const USER_ROLE_APPS = 'apps'; public const USER_ROLE_SYSTEM = 'system'; + /** + * Audit User Types. + */ + public const AUDIT_TYPE_APP = 'app'; + public const AUDIT_TYPE_USER = 'user'; + /** * Token Types. */ diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index f2825abddf..86ca59d3fd 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -76,8 +76,6 @@ class Audits extends Action 'userEmail' => $userEmail, 'mode' => $mode, 'data' => $auditPayload, - 'keyName' => $user->getAttribute('keyName'), - 'userType' => $user->getAttribute('userType'), ] ); } From f4f0b3f0fe69f035c34381fc9d8c414212f896a9 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Sun, 12 Jan 2025 17:06:27 +0530 Subject: [PATCH 258/340] add: `userType`to audit data. --- src/Appwrite/Platform/Workers/Audits.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 86ca59d3fd..2c1cb488ad 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Workers; +use Appwrite\Auth\Auth; use Exception; use Throwable; use Utopia\Audit\Audit; @@ -60,6 +61,7 @@ class Audits extends Action $userName = $user->getAttribute('name', ''); $userEmail = $user->getAttribute('email', ''); + $userType = $user->getAttribute('type', Auth::AUDIT_TYPE_USER); $audit = new Audit($dbForProject); $audit->log( @@ -74,6 +76,7 @@ class Audits extends Action 'userId' => $user->getId(), 'userName' => $userName, 'userEmail' => $userEmail, + 'userType' => $userType, 'mode' => $mode, 'data' => $auditPayload, ] From 377627118f9fc475f8de20aa3a102559cf43062f Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Sun, 12 Jan 2025 18:27:58 +0530 Subject: [PATCH 259/340] address comments: change type names. --- app/controllers/shared/api.php | 8 ++++---- src/Appwrite/Auth/Auth.php | 6 +++--- src/Appwrite/Platform/Workers/Audits.php | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index dfb491594d..d27794d9b8 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -244,7 +244,7 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, - 'type' => Auth::AUDIT_TYPE_APP, + 'type' => Auth::ACTIVITY_TYPE_APP, 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', 'name' => 'Dynamic Key', @@ -269,7 +269,7 @@ App::init() $user = new Document([ '$id' => '', 'status' => true, - 'type' => Auth::AUDIT_TYPE_APP, + 'type' => Auth::ACTIVITY_TYPE_APP, 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', 'name' => $key->getAttribute('name', 'UNKNOWN'), @@ -521,7 +521,7 @@ App::init() // check first, // as api key user might already exists if (!$user->isEmpty()) { - $user->setAttribute('type', Auth::AUDIT_TYPE_USER); + $user->setAttribute('type', Auth::ACTIVITY_TYPE_USER); $queueForAudits->setUser($user); } @@ -723,7 +723,7 @@ App::shutdown() } if (!$user->isEmpty()) { - $user->setAttribute('type', Auth::AUDIT_TYPE_USER); + $user->setAttribute('type', Auth::ACTIVITY_TYPE_USER); $queueForAudits->setUser($user); } diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index a2bb2dea1c..c8ce06a323 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -44,10 +44,10 @@ class Auth public const USER_ROLE_SYSTEM = 'system'; /** - * Audit User Types. + * Activity associated with user or the app. */ - public const AUDIT_TYPE_APP = 'app'; - public const AUDIT_TYPE_USER = 'user'; + public const ACTIVITY_TYPE_APP = 'app'; + public const ACTIVITY_TYPE_USER = 'user'; /** * Token Types. diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 2c1cb488ad..c0bcab1c3a 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -61,7 +61,7 @@ class Audits extends Action $userName = $user->getAttribute('name', ''); $userEmail = $user->getAttribute('email', ''); - $userType = $user->getAttribute('type', Auth::AUDIT_TYPE_USER); + $userType = $user->getAttribute('type', Auth::ACTIVITY_TYPE_USER); $audit = new Audit($dbForProject); $audit->log( From 00a5b8fbb9a952e4f3313fe34e903c434993f3b2 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Mon, 13 Jan 2025 14:58:03 +1300 Subject: [PATCH 260/340] Revert "Update database" This reverts commit a45e0a59dd968ea566555e97873d539c2ebbf338. # Conflicts: # composer.lock --- app/init.php | 2 +- app/realtime.php | 2 +- app/worker.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/init.php b/app/init.php index c8ee09da8d..0a241813b5 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,7 @@ use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use PHPMailer\PHPMailer\PHPMailer; use Swoole\Database\PDOProxy; -use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Adapter\Sharding; diff --git a/app/realtime.php b/app/realtime.php index 3c543ee166..86f9c85fdd 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; diff --git a/app/worker.php b/app/worker.php index b45eec6d4f..6eb1363e9b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -17,7 +17,7 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; -use Utopia\Abuse\Adapters\Redis\TimeLimit as TimeLimitRedis; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; From 10e036958ae3df7a845f91122b31f2bc5530ea60 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Mon, 13 Jan 2025 15:28:30 +1300 Subject: [PATCH 261/340] Update libraries --- composer.json | 4 ++-- composer.lock | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index f66968e348..882be5b94e 100644 --- a/composer.json +++ b/composer.json @@ -45,9 +45,9 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.43.*", + "utopia-php/abuse": "0.46.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.43.*", + "utopia-php/audit": "0.46.*", "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", diff --git a/composer.lock b/composer.lock index 13c76ab59a..b77915f0a4 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": "630e10509c6effad82583cd67ad49974", + "content-hash": "c88950f1d3119d0764a469e1d804ce71", "packages": [ { "name": "adhocore/jwt", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.4", + "version": "0.46.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9" + "reference": "59749df988430b28953fb5cabfad88b0ff5b539b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9", - "reference": "2f5d9dcf96f41a1a1e1a2ede00b49531ac8cacd9", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/59749df988430b28953fb5cabfad88b0ff5b539b", + "reference": "59749df988430b28953fb5cabfad88b0ff5b539b", "shasum": "" }, "require": { @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.4" + "source": "https://github.com/utopia-php/abuse/tree/0.46.2" }, - "time": "2025-01-10T08:58:29+00:00" + "time": "2025-01-13T02:09:43+00:00" }, { "name": "utopia-php/analytics", @@ -3233,16 +3233,16 @@ }, { "name": "utopia-php/audit", - "version": "0.43.4", + "version": "0.46.1", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7" + "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7", - "reference": "d9fe89b67c41215e94ae7bf46cd7e3dd73867dd7", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/21255fa1ce66433140a43d380b2859c7f0a0bb37", + "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37", "shasum": "" }, "require": { @@ -3274,9 +3274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.43.4" + "source": "https://github.com/utopia-php/audit/tree/0.46.1" }, - "time": "2025-01-10T08:57:54+00:00" + "time": "2025-01-13T02:19:56+00:00" }, { "name": "utopia-php/cache", From cde1d6e83e0c696b326cb310109b67bf3e316ae7 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 8 Jan 2025 15:00:15 +0530 Subject: [PATCH 262/340] Merge pull request #9190 from appwrite/fix-dead-connections Fix dead connections # Conflicts: # composer.lock --- app/controllers/general.php | 14 ++++++++++- app/http.php | 11 ++++++++ app/init.php | 31 +++++++++++++++++------ app/worker.php | 50 +++++++++++++++++++++++-------------- composer.json | 2 +- composer.lock | 22 ++++++++-------- 6 files changed, 90 insertions(+), 40 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index db9df71341..90cb3293e6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -21,6 +21,7 @@ use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; +use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Utopia\App; use Utopia\CLI\Console; @@ -28,6 +29,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -38,6 +40,7 @@ use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Logger\Logger; +use Utopia\Pools\Connection; use Utopia\System\System; use Utopia\Validator\Hostname; use Utopia\Validator\Text; @@ -746,7 +749,16 @@ App::error() ->inject('logger') ->inject('log') ->inject('queueForUsage') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { + ->inject('connectionForProject') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage, Connection $connectionForProject) { + if ( + ($error instanceof PDOException || $error instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($error) + ) { + // Mark connection as unhealthy so it will be recycled on next reclaim. + $connectionForProject->setHealthy(false); + } + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); diff --git a/app/http.php b/app/http.php index 3a7562ffd1..b988c7d8ac 100644 --- a/app/http.php +++ b/app/http.php @@ -5,6 +5,7 @@ require_once __DIR__ . '/../vendor/autoload.php'; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Constant; +use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; @@ -17,6 +18,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -346,6 +348,15 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $app->run($request, $response); } catch (\Throwable $th) { + if ( + ($th instanceof PDOException || $th instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($th) + ) { + // Mark connection as unhealthy so it will be recycled on next reclaim. + $connectionForProject = $app->getResource('connectionForProject'); + $connectionForProject->setHealthy(false); + } + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $logger = $app->getResource("logger"); diff --git a/app/init.php b/app/init.php index 0a241813b5..acaf3daaca 100644 --- a/app/init.php +++ b/app/init.php @@ -74,6 +74,7 @@ use Utopia\Logger\Adapter\Raygun; use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Logger; +use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Pools\Pool; use Utopia\Queue; @@ -1412,7 +1413,26 @@ App::setResource('console', function () { ]); }, []); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('connectionForProject', function (Group $pools, Document $project) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $pools + ->get('console') + ->pop(); + } + + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + + return $pools + ->get($dsn->getHost()) + ->pop(); +}, ['pools', 'project']); + +App::setResource('dbForProject', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -1424,12 +1444,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $database = new Database($connectionForProject->getResource(), $cache); $database ->setMetadata('host', \gethostname()) @@ -1452,7 +1467,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform } return $database; -}, ['pools', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache', 'project']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $dbAdapter = $pools diff --git a/app/worker.php b/app/worker.php index 6eb1363e9b..62882b32b1 100644 --- a/app/worker.php +++ b/app/worker.php @@ -16,6 +16,7 @@ use Appwrite\Event\Migration; use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; +use Swoole\Database\DetectsLostConnections; use Swoole\Runtime; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; @@ -25,11 +26,13 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; +use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Queue\Connection; use Utopia\Queue\Message; @@ -66,13 +69,13 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { +Server::setResource('connectionForProject', function (Group $pools, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForPlatform; + return $pools + ->get('console') + ->pop(); } - $pools = $register->get('pools'); - try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -80,12 +83,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $adapter = $pools + return $pools ->get($dsn->getHost()) - ->pop() - ->getResource(); + ->pop(); +}, ['pools', 'project']); - $database = new Database($adapter, $cache); +Server::setResource('dbForProject', function (PoolConnection $connectionForProject, Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $dbForPlatform; + } + + $database = new Database($connectionForProject->getResource(), $cache); try { $dsn = new DSN($project->getAttribute('database')); @@ -109,12 +117,12 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, } return $database; -}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['connectionForProject', 'cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $connectionForProject, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -146,12 +154,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf return $database; } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $database = new Database($connectionForProject->getResource(), $cache); $databases[$dsn->getHost()] = $database; @@ -171,7 +174,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf return $database; }; -}, ['pools', 'dbForPlatform', 'cache']); +}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); @@ -410,7 +413,16 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) { + ->inject('connectionForProject') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, PoolConnection $connectionForProject) use ($queueName) { + if ( + ($error instanceof PDOException || $error instanceof DatabaseException) + && DetectsLostConnections::causedByLostConnection($error) + ) { + // Mark connection as unhealthy, it will be recycled on next reclaim. + $connectionForProject->setHealthy(false); + } + $pools->reclaim(); $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); diff --git a/composer.json b/composer.json index 882be5b94e..bc51d6b359 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.5.*", + "utopia-php/pools": "0.6.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index b77915f0a4..c42c52d403 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": "c88950f1d3119d0764a469e1d804ce71", + "content-hash": "a84318e49e4ac82fac110ef65a2847ea", "packages": [ { "name": "adhocore/jwt", @@ -4145,25 +4145,25 @@ }, { "name": "utopia-php/pools", - "version": "0.5.0", + "version": "0.6.0", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" + "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/59414ab7b57728edfde6d5ccc5a2583b7967ac18", + "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18", "shasum": "" }, "require": { - "php": ">=8.0" + "php": ">=8.3" }, "require-dev": { - "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.8.*", - "phpunit/phpunit": "^9.3" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*" }, "type": "library", "autoload": { @@ -4190,9 +4190,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.5.0" + "source": "https://github.com/utopia-php/pools/tree/0.6.0" }, - "time": "2024-04-19T11:11:54+00:00" + "time": "2025-01-08T07:58:42+00:00" }, { "name": "utopia-php/preloader", From d997b558dc750dd7038033839e823cb406ac2544 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Mon, 13 Jan 2025 11:20:17 +0530 Subject: [PATCH 263/340] update: there are no multiple connections for logs. As confirmed by Damodar, Logs DB is similar to Console DB. so no multiple connections. --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index af83368082..5a4731c1e6 100644 --- a/app/init.php +++ b/app/init.php @@ -872,7 +872,7 @@ $register->set('pools', function () { 'logs' => [ 'type' => 'database', 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB), - 'multiple' => true, + 'multiple' => false, 'schemes' => ['mariadb', 'mysql'], ], 'queue' => [ From 1cd7c397decc498b0e8aba18fdda9f5c1c7abf77 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Mon, 13 Jan 2025 19:24:58 +1300 Subject: [PATCH 264/340] Revert "Fix dead connections" --- app/controllers/general.php | 14 +---------- app/http.php | 11 -------- app/init.php | 31 ++++++----------------- app/worker.php | 50 ++++++++++++++----------------------- composer.json | 2 +- composer.lock | 22 ++++++++-------- 6 files changed, 40 insertions(+), 90 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 90cb3293e6..db9df71341 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -21,7 +21,6 @@ use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; -use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Utopia\App; use Utopia\CLI\Console; @@ -29,7 +28,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -40,7 +38,6 @@ use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Logger\Logger; -use Utopia\Pools\Connection; use Utopia\System\System; use Utopia\Validator\Hostname; use Utopia\Validator\Text; @@ -749,16 +746,7 @@ App::error() ->inject('logger') ->inject('log') ->inject('queueForUsage') - ->inject('connectionForProject') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage, Connection $connectionForProject) { - if ( - ($error instanceof PDOException || $error instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($error) - ) { - // Mark connection as unhealthy so it will be recycled on next reclaim. - $connectionForProject->setHealthy(false); - } - + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); diff --git a/app/http.php b/app/http.php index b988c7d8ac..3a7562ffd1 100644 --- a/app/http.php +++ b/app/http.php @@ -5,7 +5,6 @@ require_once __DIR__ . '/../vendor/autoload.php'; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Constant; -use Swoole\Database\DetectsLostConnections; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; @@ -18,7 +17,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -348,15 +346,6 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $app->run($request, $response); } catch (\Throwable $th) { - if ( - ($th instanceof PDOException || $th instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($th) - ) { - // Mark connection as unhealthy so it will be recycled on next reclaim. - $connectionForProject = $app->getResource('connectionForProject'); - $connectionForProject->setHealthy(false); - } - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $logger = $app->getResource("logger"); diff --git a/app/init.php b/app/init.php index acaf3daaca..0a241813b5 100644 --- a/app/init.php +++ b/app/init.php @@ -74,7 +74,6 @@ use Utopia\Logger\Adapter\Raygun; use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Logger; -use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Pools\Pool; use Utopia\Queue; @@ -1413,26 +1412,7 @@ App::setResource('console', function () { ]); }, []); -App::setResource('connectionForProject', function (Group $pools, Document $project) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $pools - ->get('console') - ->pop(); - } - - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - - return $pools - ->get($dsn->getHost()) - ->pop(); -}, ['pools', 'project']); - -App::setResource('dbForProject', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, Cache $cache, Document $project) { +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -1444,7 +1424,12 @@ App::setResource('dbForProject', function (Group $pools, PoolConnection $connect $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $database = new Database($connectionForProject->getResource(), $cache); + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); $database ->setMetadata('host', \gethostname()) @@ -1467,7 +1452,7 @@ App::setResource('dbForProject', function (Group $pools, PoolConnection $connect } return $database; -}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache', 'project']); +}, ['pools', 'dbForPlatform', 'cache', 'project']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { $dbAdapter = $pools diff --git a/app/worker.php b/app/worker.php index 62882b32b1..6eb1363e9b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -16,7 +16,6 @@ use Appwrite\Event\Migration; use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; -use Swoole\Database\DetectsLostConnections; use Swoole\Runtime; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; @@ -26,13 +25,11 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; -use Utopia\Pools\Connection as PoolConnection; use Utopia\Pools\Group; use Utopia\Queue\Connection; use Utopia\Queue\Message; @@ -69,13 +66,13 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo return $dbForPlatform->getDocument('projects', $project->getId()); }, ['message', 'dbForPlatform']); -Server::setResource('connectionForProject', function (Group $pools, Document $project) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { - return $pools - ->get('console') - ->pop(); + return $dbForPlatform; } + $pools = $register->get('pools'); + try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -83,17 +80,12 @@ Server::setResource('connectionForProject', function (Group $pools, Document $pr $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - return $pools + $adapter = $pools ->get($dsn->getHost()) - ->pop(); -}, ['pools', 'project']); + ->pop() + ->getResource(); -Server::setResource('dbForProject', function (PoolConnection $connectionForProject, Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForPlatform; - } - - $database = new Database($connectionForProject->getResource(), $cache); + $database = new Database($adapter, $cache); try { $dsn = new DSN($project->getAttribute('database')); @@ -117,12 +109,12 @@ Server::setResource('dbForProject', function (PoolConnection $connectionForProje } return $database; -}, ['connectionForProject', 'cache', 'register', 'message', 'project', 'dbForPlatform']); +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); -Server::setResource('getProjectDB', function (Group $pools, PoolConnection $connectionForProject, Database $dbForPlatform, $cache) { +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $connectionForProject, $dbForPlatform, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForPlatform; } @@ -154,7 +146,12 @@ Server::setResource('getProjectDB', function (Group $pools, PoolConnection $conn return $database; } - $database = new Database($connectionForProject->getResource(), $cache); + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); $databases[$dsn->getHost()] = $database; @@ -174,7 +171,7 @@ Server::setResource('getProjectDB', function (Group $pools, PoolConnection $conn return $database; }; -}, ['pools', 'connectionForProject', 'dbForPlatform', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); Server::setResource('abuseRetention', function () { return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); @@ -413,16 +410,7 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->inject('connectionForProject') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, PoolConnection $connectionForProject) use ($queueName) { - if ( - ($error instanceof PDOException || $error instanceof DatabaseException) - && DetectsLostConnections::causedByLostConnection($error) - ) { - // Mark connection as unhealthy, it will be recycled on next reclaim. - $connectionForProject->setHealthy(false); - } - + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) { $pools->reclaim(); $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); diff --git a/composer.json b/composer.json index bc51d6b359..882be5b94e 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.6.*", + "utopia-php/pools": "0.5.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index c42c52d403..b77915f0a4 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": "a84318e49e4ac82fac110ef65a2847ea", + "content-hash": "c88950f1d3119d0764a469e1d804ce71", "packages": [ { "name": "adhocore/jwt", @@ -4145,25 +4145,25 @@ }, { "name": "utopia-php/pools", - "version": "0.6.0", + "version": "0.5.0", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18" + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/59414ab7b57728edfde6d5ccc5a2583b7967ac18", - "reference": "59414ab7b57728edfde6d5ccc5a2583b7967ac18", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.0" }, "require-dev": { - "laravel/pint": "1.*", - "phpstan/phpstan": "1.*", - "phpunit/phpunit": "11.*" + "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.8.*", + "phpunit/phpunit": "^9.3" }, "type": "library", "autoload": { @@ -4190,9 +4190,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.6.0" + "source": "https://github.com/utopia-php/pools/tree/0.5.0" }, - "time": "2025-01-08T07:58:42+00:00" + "time": "2024-04-19T11:11:54+00:00" }, { "name": "utopia-php/preloader", From b5449a8ca6f547054972af93178a7c41e497dd37 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 13 Jan 2025 18:25:48 +0000 Subject: [PATCH 265/340] fix: resend invitation --- app/controllers/api/teams.php | 62 ++++++++++++-------- tests/e2e/Services/Teams/TeamsBaseClient.php | 10 +++- tests/e2e/Services/Teams/TeamsBaseServer.php | 10 +++- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 461e90da58..0ab166e28d 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -546,33 +546,45 @@ App::post('/v1/teams/:teamId/memberships') throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team'); } - $secret = Auth::tokenGenerator(); - - $membershipId = ID::unique(); - $membership = new Document([ - '$id' => $membershipId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($invitee->getId())), - Permission::update(Role::team($team->getId(), 'owner')), - Permission::delete(Role::user($invitee->getId())), - Permission::delete(Role::team($team->getId(), 'owner')), - ], - 'userId' => $invitee->getId(), - 'userInternalId' => $invitee->getInternalId(), - 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), - 'roles' => $roles, - 'invited' => DateTime::now(), - 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, - 'confirm' => ($isPrivilegedUser || $isAppUser), - 'secret' => Auth::hash($secret), - 'search' => implode(' ', [$membershipId, $invitee->getId()]) + $membership = $dbForProject->findOne('memberships', [ + Query::equal('userId', [$invitee->getId()]), + Query::equal('teamId', [$team->getId()]), ]); + $createdMembership = false; + + if ($membership->isEmpty()) { + $secret = Auth::tokenGenerator(); + + $membershipId = ID::unique(); + $membership = new Document([ + '$id' => $membershipId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($invitee->getId())), + Permission::update(Role::team($team->getId(), 'owner')), + Permission::delete(Role::user($invitee->getId())), + Permission::delete(Role::team($team->getId(), 'owner')), + ], + 'userId' => $invitee->getId(), + 'userInternalId' => $invitee->getInternalId(), + 'teamId' => $team->getId(), + 'teamInternalId' => $team->getInternalId(), + 'roles' => $roles, + 'invited' => DateTime::now(), + 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, + 'confirm' => ($isPrivilegedUser || $isAppUser), + 'secret' => Auth::hash($secret), + 'search' => implode(' ', [$membershipId, $invitee->getId()]) + ]); + + $createdMembership = true; + } if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership try { - $membership = Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)); + $membership = $createdMembership ? + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)); } catch (Duplicate $th) { throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); } @@ -582,7 +594,9 @@ App::post('/v1/teams/:teamId/memberships') $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { try { - $membership = $dbForProject->createDocument('memberships', $membership); + $membership = $createdMembership ? + $dbForProject->createDocument('memberships', $membership) : + $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } catch (Duplicate $th) { throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); } diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index ca6082f6d0..cf011d2bf7 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -292,9 +292,9 @@ trait TeamsBaseClient $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); /** - * Test for FAILURE + * Test for resend + * SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -305,7 +305,11 @@ trait TeamsBaseClient 'url' => 'http://localhost:5000/join-us#title' ]); - $this->assertEquals(409, $response['headers']['status-code']); + $this->assertEquals(201, $response['headers']['status-code']); + + /** + * Test for FAILURE + */ $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 6a1d05e9d4..226536c604 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -186,9 +186,9 @@ trait TeamsBaseServer // $this->assertContains('team:'.$teamUid.'/editor', $response['body']['roles']); /** - * Test for FAILURE + * Test for resend + * SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -199,7 +199,11 @@ trait TeamsBaseServer 'url' => 'http://localhost:5000/join-us#title' ]); - $this->assertEquals(409, $response['headers']['status-code']); + $this->assertEquals(201, $response['headers']['status-code']); + + /** + * Test for FAILURE + */ $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', From e6cb17a6cc99ad73bcc65c6e18aad944d66b6b35 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 13 Jan 2025 18:51:23 +0000 Subject: [PATCH 266/340] chore: remove TEAM_INVITE_ALREADY_EXISTS --- app/config/errors.php | 5 ----- app/controllers/api/teams.php | 26 ++++++++++++-------------- src/Appwrite/Extend/Exception.php | 1 - 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index f09d1596eb..1c32accdb4 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -349,11 +349,6 @@ return [ 'description' => 'Team with the requested ID could not be found.', 'code' => 404, ], - Exception::TEAM_INVITE_ALREADY_EXISTS => [ - 'name' => Exception::TEAM_INVITE_ALREADY_EXISTS, - 'description' => 'User has already been invited or is already a member of this team', - 'code' => 409, - ], Exception::TEAM_INVITE_NOT_FOUND => [ 'name' => Exception::TEAM_INVITE_NOT_FOUND, 'description' => 'The requested team invitation could not be found.', diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 0ab166e28d..829d452cae 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -581,24 +581,22 @@ App::post('/v1/teams/:teamId/memberships') } if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership - try { - $membership = $createdMembership ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)); - } catch (Duplicate $th) { - throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); - } + $membership = $createdMembership ? + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)); - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + if ($createdMembership) { + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + } $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { - try { - $membership = $createdMembership ? - $dbForProject->createDocument('memberships', $membership) : - $dbForProject->updateDocument('memberships', $membership->getId(), $membership); - } catch (Duplicate $th) { - throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); + $membership = $createdMembership ? + $dbForProject->createDocument('memberships', $membership) : + $dbForProject->updateDocument('memberships', $membership->getId(), $membership); + + if ($createdMembership) { + $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1); } $url = Template::parseURL($url); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 54bf6d96ea..4a6959f332 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -112,7 +112,6 @@ class Exception extends \Exception /** Teams */ public const TEAM_NOT_FOUND = 'team_not_found'; - public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; public const TEAM_INVALID_SECRET = 'team_invalid_secret'; public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; From 3fa78e3c3ba23a3d8b9eafefd4507bf7ca4c59fa Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 14 Jan 2025 14:50:40 +1300 Subject: [PATCH 267/340] Log path with populated parameters --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index db9df71341..6f8566f69b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -894,7 +894,7 @@ App::error() $log->addTag('database', $dsn->getHost()); $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); + $log->addTag('url', $request->getURI()); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); $log->addTag('projectId', $project->getId()); From e9479db0fa6dd717642b463d8e9aeabb01351312 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 14 Jan 2025 13:18:11 +0530 Subject: [PATCH 268/340] add: anonymous user type to audit/activity. --- app/controllers/shared/api.php | 20 ++++++++++++++++++++ src/Appwrite/Auth/Auth.php | 1 + 2 files changed, 21 insertions(+) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index d27794d9b8..6a0e4a34fa 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -308,6 +308,7 @@ App::init() } } + // standard api key user $queueForAudits->setUser($user); } } @@ -724,6 +725,25 @@ App::shutdown() if (!$user->isEmpty()) { $user->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($user); + } elseif ($queueForAudits->getUser() === null || $queueForAudits->getUser()->isEmpty()) { + /** + * User in the request is empty, and no user was set for auditing previously. + * This indicates: + * - No API Key was used. + * - No active session exists. + * + * Therefore, we consider this an anonymous request and create a relevant user. + */ + $user = new Document([ + '$id' => '', + 'status' => true, + 'type' => Auth::ACTIVITY_TYPE_ANONYMOUS, + 'email' => 'anonymous.' . $project->getId() . '@service.' . $request->getHostname(), + 'password' => '', + 'name' => 'Anonymous', + ]); + $queueForAudits->setUser($user); } diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index c8ce06a323..caa1e23478 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -48,6 +48,7 @@ class Auth */ public const ACTIVITY_TYPE_APP = 'app'; public const ACTIVITY_TYPE_USER = 'user'; + public const ACTIVITY_TYPE_ANONYMOUS = 'anonymous'; /** * Token Types. From fabf581d21e8641c8e042b20a8bf094893fc0028 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 14 Jan 2025 13:47:01 +0530 Subject: [PATCH 269/340] fix: tests. --- app/controllers/shared/api.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 6a0e4a34fa..a88615e729 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -522,8 +522,10 @@ App::init() // check first, // as api key user might already exists if (!$user->isEmpty()) { - $user->setAttribute('type', Auth::ACTIVITY_TYPE_USER); - $queueForAudits->setUser($user); + $typedUser = clone $user; + // $user doesn't support `type` and can cause unintended effects. + $typedUser->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($typedUser); } $queueForDeletes->setProject($project); @@ -724,8 +726,10 @@ App::shutdown() } if (!$user->isEmpty()) { - $user->setAttribute('type', Auth::ACTIVITY_TYPE_USER); - $queueForAudits->setUser($user); + $typedUser = clone $user; + // $user doesn't support `type` and can cause unintended effects. + $typedUser->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($typedUser); } elseif ($queueForAudits->getUser() === null || $queueForAudits->getUser()->isEmpty()) { /** * User in the request is empty, and no user was set for auditing previously. From 2571f7d3fc37beea50c62efdb774aef437bde0e0 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Tue, 14 Jan 2025 15:43:00 +0530 Subject: [PATCH 270/340] refactor: createdMembership --- app/controllers/api/teams.php | 266 ++++++++++++++++------------------ 1 file changed, 127 insertions(+), 139 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 829d452cae..3664afec43 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -550,7 +550,6 @@ App::post('/v1/teams/:teamId/memberships') Query::equal('userId', [$invitee->getId()]), Query::equal('teamId', [$team->getId()]), ]); - $createdMembership = false; if ($membership->isEmpty()) { $secret = Auth::tokenGenerator(); @@ -577,159 +576,148 @@ App::post('/v1/teams/:teamId/memberships') 'search' => implode(' ', [$membershipId, $invitee->getId()]) ]); - $createdMembership = true; + $membership = ($isPrivilegedUser || $isAppUser) ? + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $dbForProject->createDocument('memberships', $membership); + } else { + + $membership = ($isPrivilegedUser || $isAppUser) ? + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } - if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership - $membership = $createdMembership ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)); + $dbForProject->purgeCachedDocument('users', $invitee->getId()); - if ($createdMembership) { - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); - } + $url = Template::parseURL($url); + $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); + $url = Template::unParseURL($url); + if (!empty($email)) { + $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); - $dbForProject->purgeCachedDocument('users', $invitee->getId()); - } else { - $membership = $createdMembership ? - $dbForProject->createDocument('memberships', $membership) : - $dbForProject->updateDocument('memberships', $membership->getId(), $membership); + $body = $locale->getText("emails.invitation.body"); + $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); + $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; - if ($createdMembership) { - $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1); - } + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); + $message + ->setParam('{{body}}', $body, escapeHtml: false) + ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) + ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")); + $body = $message->render(); - $url = Template::parseURL($url); - $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); - $url = Template::unParseURL($url); - if (!empty($email)) { - $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); + $smtp = $project->getAttribute('smtp', []); + $smtpEnabled = $smtp['enabled'] ?? false; - $body = $locale->getText("emails.invitation.body"); - $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); - $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; + $senderEmail = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); + $senderName = System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'); + $replyTo = ""; - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); - $message - ->setParam('{{body}}', $body, escapeHtml: false) - ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) - ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")); - $body = $message->render(); - - $smtp = $project->getAttribute('smtp', []); - $smtpEnabled = $smtp['enabled'] ?? false; - - $senderEmail = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); - $senderName = System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'); - $replyTo = ""; - - if ($smtpEnabled) { - if (!empty($smtp['senderEmail'])) { - $senderEmail = $smtp['senderEmail']; - } - if (!empty($smtp['senderName'])) { - $senderName = $smtp['senderName']; - } - if (!empty($smtp['replyTo'])) { - $replyTo = $smtp['replyTo']; - } - - $queueForMails - ->setSmtpHost($smtp['host'] ?? '') - ->setSmtpPort($smtp['port'] ?? '') - ->setSmtpUsername($smtp['username'] ?? '') - ->setSmtpPassword($smtp['password'] ?? '') - ->setSmtpSecure($smtp['secure'] ?? ''); - - if (!empty($customTemplate)) { - if (!empty($customTemplate['senderEmail'])) { - $senderEmail = $customTemplate['senderEmail']; - } - if (!empty($customTemplate['senderName'])) { - $senderName = $customTemplate['senderName']; - } - if (!empty($customTemplate['replyTo'])) { - $replyTo = $customTemplate['replyTo']; - } - - $body = $customTemplate['message'] ?? ''; - $subject = $customTemplate['subject'] ?? $subject; - } - - $queueForMails - ->setSmtpReplyTo($replyTo) - ->setSmtpSenderEmail($senderEmail) - ->setSmtpSenderName($senderName); + if ($smtpEnabled) { + if (!empty($smtp['senderEmail'])) { + $senderEmail = $smtp['senderEmail']; + } + if (!empty($smtp['senderName'])) { + $senderName = $smtp['senderName']; + } + if (!empty($smtp['replyTo'])) { + $replyTo = $smtp['replyTo']; } - - $emailVariables = [ - 'owner' => $user->getAttribute('name'), - 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ - 'user' => $user->getAttribute('name'), - 'team' => $team->getAttribute('name'), - 'redirect' => $url, - 'project' => $projectName - ]; $queueForMails - ->setSubject($subject) - ->setBody($body) - ->setRecipient($invitee->getAttribute('email')) - ->setName($invitee->getAttribute('name')) - ->setVariables($emailVariables) - ->trigger() - ; - } elseif (!empty($phone)) { - if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { - throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); - } + ->setSmtpHost($smtp['host'] ?? '') + ->setSmtpPort($smtp['port'] ?? '') + ->setSmtpUsername($smtp['username'] ?? '') + ->setSmtpPassword($smtp['password'] ?? '') + ->setSmtpSecure($smtp['secure'] ?? ''); - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - - $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; if (!empty($customTemplate)) { - $message = $customTemplate['message']; - } - - $message = $message->setParam('{{token}}', $url); - $message = $message->render(); - - $messageDoc = new Document([ - '$id' => ID::unique(), - 'data' => [ - 'content' => $message, - ], - ]); - - $queueForMessaging - ->setType(MESSAGE_SEND_TYPE_INTERNAL) - ->setMessage($messageDoc) - ->setRecipients([$phone]) - ->setProviderType('SMS'); - - if (isset($plan['authPhone'])) { - $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days - $timelimit - ->setParam('{organizationId}', $project->getAttribute('teamId')); - - $abuse = new Abuse($timelimit); - if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { - $helper = PhoneNumberUtil::getInstance(); - $countryCode = $helper->parse($phone)->getCountryCode(); - - if (!empty($countryCode)) { - $queueForUsage - ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); - } + if (!empty($customTemplate['senderEmail'])) { + $senderEmail = $customTemplate['senderEmail']; } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); + if (!empty($customTemplate['senderName'])) { + $senderName = $customTemplate['senderName']; + } + if (!empty($customTemplate['replyTo'])) { + $replyTo = $customTemplate['replyTo']; + } + + $body = $customTemplate['message'] ?? ''; + $subject = $customTemplate['subject'] ?? $subject; } + + $queueForMails + ->setSmtpReplyTo($replyTo) + ->setSmtpSenderEmail($senderEmail) + ->setSmtpSenderName($senderName); + } + + $emailVariables = [ + 'owner' => $user->getAttribute('name'), + 'direction' => $locale->getText('settings.direction'), + /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ + 'user' => $user->getAttribute('name'), + 'team' => $team->getAttribute('name'), + 'redirect' => $url, + 'project' => $projectName + ]; + + $queueForMails + ->setSubject($subject) + ->setBody($body) + ->setRecipient($invitee->getAttribute('email')) + ->setName($invitee->getAttribute('name')) + ->setVariables($emailVariables) + ->trigger(); + + } elseif (!empty($phone)) { + if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { + throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); + } + + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + + $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; + if (!empty($customTemplate)) { + $message = $customTemplate['message']; + } + + $message = $message->setParam('{{token}}', $url); + $message = $message->render(); + + $messageDoc = new Document([ + '$id' => ID::unique(), + 'data' => [ + 'content' => $message, + ], + ]); + + $queueForMessaging + ->setType(MESSAGE_SEND_TYPE_INTERNAL) + ->setMessage($messageDoc) + ->setRecipients([$phone]) + ->setProviderType('SMS'); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); } } From 1c7867ee039f1cb3600313614616c026cf05eba3 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Tue, 14 Jan 2025 15:47:05 +0530 Subject: [PATCH 271/340] fix: not sending mail to appuser --- app/controllers/api/teams.php | 250 +++++++++++++++++----------------- 1 file changed, 127 insertions(+), 123 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 3664afec43..da6828c6bf 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -580,144 +580,148 @@ App::post('/v1/teams/:teamId/memberships') Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); } else { - + $membership = ($isPrivilegedUser || $isAppUser) ? Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } - $dbForProject->purgeCachedDocument('users', $invitee->getId()); - $url = Template::parseURL($url); - $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); - $url = Template::unParseURL($url); - if (!empty($email)) { - $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); + if (!$isPrivilegedUser && !$isAppUser) { + $dbForProject->purgeCachedDocument('users', $invitee->getId()); + } else { - $body = $locale->getText("emails.invitation.body"); - $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); - $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; + $url = Template::parseURL($url); + $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); + $url = Template::unParseURL($url); + if (!empty($email)) { + $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); - $message - ->setParam('{{body}}', $body, escapeHtml: false) - ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) - ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) - ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) - ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")); - $body = $message->render(); + $body = $locale->getText("emails.invitation.body"); + $subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName); + $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; - $smtp = $project->getAttribute('smtp', []); - $smtpEnabled = $smtp['enabled'] ?? false; + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); + $message + ->setParam('{{body}}', $body, escapeHtml: false) + ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) + ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) + ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")); + $body = $message->render(); - $senderEmail = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); - $senderName = System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'); - $replyTo = ""; + $smtp = $project->getAttribute('smtp', []); + $smtpEnabled = $smtp['enabled'] ?? false; - if ($smtpEnabled) { - if (!empty($smtp['senderEmail'])) { - $senderEmail = $smtp['senderEmail']; - } - if (!empty($smtp['senderName'])) { - $senderName = $smtp['senderName']; - } - if (!empty($smtp['replyTo'])) { - $replyTo = $smtp['replyTo']; + $senderEmail = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); + $senderName = System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'); + $replyTo = ""; + + if ($smtpEnabled) { + if (!empty($smtp['senderEmail'])) { + $senderEmail = $smtp['senderEmail']; + } + if (!empty($smtp['senderName'])) { + $senderName = $smtp['senderName']; + } + if (!empty($smtp['replyTo'])) { + $replyTo = $smtp['replyTo']; + } + + $queueForMails + ->setSmtpHost($smtp['host'] ?? '') + ->setSmtpPort($smtp['port'] ?? '') + ->setSmtpUsername($smtp['username'] ?? '') + ->setSmtpPassword($smtp['password'] ?? '') + ->setSmtpSecure($smtp['secure'] ?? ''); + + if (!empty($customTemplate)) { + if (!empty($customTemplate['senderEmail'])) { + $senderEmail = $customTemplate['senderEmail']; + } + if (!empty($customTemplate['senderName'])) { + $senderName = $customTemplate['senderName']; + } + if (!empty($customTemplate['replyTo'])) { + $replyTo = $customTemplate['replyTo']; + } + + $body = $customTemplate['message'] ?? ''; + $subject = $customTemplate['subject'] ?? $subject; + } + + $queueForMails + ->setSmtpReplyTo($replyTo) + ->setSmtpSenderEmail($senderEmail) + ->setSmtpSenderName($senderName); } + $emailVariables = [ + 'owner' => $user->getAttribute('name'), + 'direction' => $locale->getText('settings.direction'), + /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ + 'user' => $user->getAttribute('name'), + 'team' => $team->getAttribute('name'), + 'redirect' => $url, + 'project' => $projectName + ]; + $queueForMails - ->setSmtpHost($smtp['host'] ?? '') - ->setSmtpPort($smtp['port'] ?? '') - ->setSmtpUsername($smtp['username'] ?? '') - ->setSmtpPassword($smtp['password'] ?? '') - ->setSmtpSecure($smtp['secure'] ?? ''); - - if (!empty($customTemplate)) { - if (!empty($customTemplate['senderEmail'])) { - $senderEmail = $customTemplate['senderEmail']; - } - if (!empty($customTemplate['senderName'])) { - $senderName = $customTemplate['senderName']; - } - if (!empty($customTemplate['replyTo'])) { - $replyTo = $customTemplate['replyTo']; - } - - $body = $customTemplate['message'] ?? ''; - $subject = $customTemplate['subject'] ?? $subject; - } - - $queueForMails - ->setSmtpReplyTo($replyTo) - ->setSmtpSenderEmail($senderEmail) - ->setSmtpSenderName($senderName); - } - - $emailVariables = [ - 'owner' => $user->getAttribute('name'), - 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ - 'user' => $user->getAttribute('name'), - 'team' => $team->getAttribute('name'), - 'redirect' => $url, - 'project' => $projectName - ]; - - $queueForMails - ->setSubject($subject) - ->setBody($body) - ->setRecipient($invitee->getAttribute('email')) - ->setName($invitee->getAttribute('name')) - ->setVariables($emailVariables) - ->trigger(); - - } elseif (!empty($phone)) { - if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { - throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); - } - - $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - - $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; - if (!empty($customTemplate)) { - $message = $customTemplate['message']; - } - - $message = $message->setParam('{{token}}', $url); - $message = $message->render(); - - $messageDoc = new Document([ - '$id' => ID::unique(), - 'data' => [ - 'content' => $message, - ], - ]); - - $queueForMessaging - ->setType(MESSAGE_SEND_TYPE_INTERNAL) - ->setMessage($messageDoc) - ->setRecipients([$phone]) - ->setProviderType('SMS'); - - if (isset($plan['authPhone'])) { - $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days - $timelimit - ->setParam('{organizationId}', $project->getAttribute('teamId')); - - $abuse = new Abuse($timelimit); - if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { - $helper = PhoneNumberUtil::getInstance(); - $countryCode = $helper->parse($phone)->getCountryCode(); - - if (!empty($countryCode)) { - $queueForUsage - ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); - } - } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) + ->setSubject($subject) + ->setBody($body) + ->setRecipient($invitee->getAttribute('email')) + ->setName($invitee->getAttribute('name')) + ->setVariables($emailVariables) ->trigger(); + + } elseif (!empty($phone)) { + if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { + throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); + } + + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + + $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; + if (!empty($customTemplate)) { + $message = $customTemplate['message']; + } + + $message = $message->setParam('{{token}}', $url); + $message = $message->render(); + + $messageDoc = new Document([ + '$id' => ID::unique(), + 'data' => [ + 'content' => $message, + ], + ]); + + $queueForMessaging + ->setType(MESSAGE_SEND_TYPE_INTERNAL) + ->setMessage($messageDoc) + ->setRecipients([$phone]) + ->setProviderType('SMS'); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } } } From 860c917cf64a8242087e0c213ef492df119293fb Mon Sep 17 00:00:00 2001 From: ChiragAgg5k <chiragaggarwal5k@gmail.com> Date: Tue, 14 Jan 2025 15:48:28 +0530 Subject: [PATCH 272/340] fix: increment --- app/controllers/api/teams.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index da6828c6bf..c30251a62b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -579,8 +579,9 @@ App::post('/v1/teams/:teamId/memberships') $membership = ($isPrivilegedUser || $isAppUser) ? Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); - } else { + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + } else { $membership = ($isPrivilegedUser || $isAppUser) ? Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); @@ -590,7 +591,6 @@ App::post('/v1/teams/:teamId/memberships') if (!$isPrivilegedUser && !$isAppUser) { $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { - $url = Template::parseURL($url); $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); $url = Template::unParseURL($url); From d43507040c166199d0831aece6dd24c6c54903bd Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Tue, 14 Jan 2025 10:43:32 +0000 Subject: [PATCH 273/340] fix: tests --- app/controllers/api/teams.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index c30251a62b..feb1cb4acd 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -588,7 +588,7 @@ App::post('/v1/teams/:teamId/memberships') } - if (!$isPrivilegedUser && !$isAppUser) { + if ($isPrivilegedUser || $isAppUser) { $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { $url = Template::parseURL($url); From 25431adafb3229f968d6bde2fd55fbba2e072f2c Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 14 Jan 2025 17:45:49 +0530 Subject: [PATCH 274/340] address comment: anonymous > guest. --- app/controllers/shared/api.php | 6 +++--- src/Appwrite/Auth/Auth.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index a88615e729..6c90e6ed60 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -742,10 +742,10 @@ App::shutdown() $user = new Document([ '$id' => '', 'status' => true, - 'type' => Auth::ACTIVITY_TYPE_ANONYMOUS, - 'email' => 'anonymous.' . $project->getId() . '@service.' . $request->getHostname(), + 'type' => Auth::ACTIVITY_TYPE_GUEST, + 'email' => 'guest.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', - 'name' => 'Anonymous', + 'name' => 'Guest', ]); $queueForAudits->setUser($user); diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index caa1e23478..8555d5cb00 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -48,7 +48,7 @@ class Auth */ public const ACTIVITY_TYPE_APP = 'app'; public const ACTIVITY_TYPE_USER = 'user'; - public const ACTIVITY_TYPE_ANONYMOUS = 'anonymous'; + public const ACTIVITY_TYPE_GUEST = 'guest'; /** * Token Types. From a7f40708a396a6e76b2331b82790f3928b837b46 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 15 Jan 2025 15:20:15 +1300 Subject: [PATCH 275/340] Update lock --- composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index a4bffa3416..4db1b5b4e7 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": "4ce4526b10d26830d8f9eaf55e40135c", + "content-hash": "f80fb401ae4c587e1f79daa5f6215329", "packages": [ { "name": "adhocore/jwt", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "a67772f8be70f75fa60bab49c38c95048f4dc8cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/a67772f8be70f75fa60bab49c38c95048f4dc8cf", + "reference": "a67772f8be70f75fa60bab49c38c95048f4dc8cf", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.2" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-01-14T08:23:27+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2025-01-14T16:20:53+00:00" }, { "name": "matthiasmullie/minify", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From c0a0f1016ec1c22ba8a76b9c45f8ab57d2197d7d Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 15 Jan 2025 18:36:30 +1300 Subject: [PATCH 276/340] Revert platform update --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 5f354dff39..4e1b5a98a2 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/messaging": "0.13.*", "utopia-php/migration": "0.6.*", "utopia-php/orchestration": "0.9.*", - "utopia-php/platform": "0.7.*", + "utopia-php/platform": "0.7.1", "utopia-php/pools": "0.5.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", diff --git a/composer.lock b/composer.lock index 4db1b5b4e7..68dbc191bf 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": "f80fb401ae4c587e1f79daa5f6215329", + "content-hash": "3853435a659889e86c16764046950bed", "packages": [ { "name": "adhocore/jwt", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.2", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "a67772f8be70f75fa60bab49c38c95048f4dc8cf" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/a67772f8be70f75fa60bab49c38c95048f4dc8cf", - "reference": "a67772f8be70f75fa60bab49c38c95048f4dc8cf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2025-01-14T08:23:27+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", From bbeb9d47199dd99c957f8c842c7b9754fc663b68 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 10:13:30 +0200 Subject: [PATCH 277/340] Add relatedCollection default --- src/Appwrite/Platform/Workers/Databases.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index c16fba36c1..5b73e6a75c 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -136,6 +136,9 @@ class Databases extends Action $options = $attribute->getAttribute('options', []); $project = $dbForPlatform->getDocument('projects', $projectId); + $relatedAttribute = new Document(); + $relatedCollection = new Document(); + try { switch ($type) { case Database::VAR_RELATIONSHIP: @@ -175,7 +178,7 @@ class Databases extends Action if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (isset($relatedAttribute)) { + if (! $relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } @@ -186,7 +189,7 @@ class Databases extends Action $attribute->setAttribute('status', 'failed') ); - if (isset($relatedAttribute)) { + if (! $relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), @@ -198,7 +201,7 @@ class Databases extends Action } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); - if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + if (! $relatedCollection->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } @@ -364,7 +367,7 @@ class Databases extends Action } finally { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { + if (! $relatedCollection->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } } From 42ef7fd2d89e4c137ef48dff80ead5caa84b69ba Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 11:16:10 +0200 Subject: [PATCH 278/340] INDEX_DEPENDENCY --- app/config/errors.php | 5 +++++ app/controllers/general.php | 4 ++++ src/Appwrite/Extend/Exception.php | 1 + 3 files changed, 10 insertions(+) diff --git a/app/config/errors.php b/app/config/errors.php index f09d1596eb..ae1aae01c4 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -731,6 +731,11 @@ return [ 'description' => 'Index invalid.', 'code' => 400, ], + Exception::INDEX_DEPENDENCY => [ + 'name' => Exception::INDEX_DEPENDENCY, + 'description' => 'Attribute cannot be renamed or deleted. Please remove the associated index first.', + 'code' => 400, + ], /** Project Errors */ Exception::PROJECT_NOT_FOUND => [ diff --git a/app/controllers/general.php b/app/controllers/general.php index 6f8566f69b..7772b91c1c 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -808,6 +808,10 @@ App::error() break; case 'Utopia\Database\Exception\NotFound': $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); + break; + case 'Utopia\Database\Exception\Dependency': + $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, $error->getMessage(), previous: $error); + break; } $code = $error->getCode(); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 54bf6d96ea..432a5abb1b 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -211,6 +211,7 @@ class Exception extends \Exception public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; public const INDEX_ALREADY_EXISTS = 'index_already_exists'; public const INDEX_INVALID = 'index_invalid'; + public const INDEX_DEPENDENCY = 'index_dependency'; /** Projects */ public const PROJECT_NOT_FOUND = 'project_not_found'; From 719c0bf4406c1912ad9e0a8c526761e1027b3116 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 11:45:26 +0200 Subject: [PATCH 279/340] composer.lock --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index b77915f0a4..43b7b4c111 100644 --- a/composer.lock +++ b/composer.lock @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.2" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-01-15T05:56:26+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2025-01-14T16:20:53+00:00" }, { "name": "matthiasmullie/minify", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From a1566b89746695810016ace8f92adbb81bc978f5 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 11:46:07 +0200 Subject: [PATCH 280/340] composer.lock --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 43b7b4c111..b77915f0a4 100644 --- a/composer.lock +++ b/composer.lock @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.2", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2025-01-15T05:56:26+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.20.0", + "version": "v1.19.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-01-14T16:20:53+00:00" + "time": "2024-12-30T16:20:10+00:00" }, { "name": "matthiasmullie/minify", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 43db5b4552b35685cabe05596eb045c7d7861be5 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 13:10:03 +0200 Subject: [PATCH 281/340] catch Dependency --- src/Appwrite/Platform/Workers/Databases.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 5b73e6a75c..fb13de3941 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -278,6 +278,17 @@ class Databases extends Action $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } + } catch (DatabaseException\Dependency $e) { + Console::error($e->getMessage()); + + $dbForProject->updateDocument( + 'attributes', + $attribute->getId(), + $attribute->setAttribute('error', $e->getMessage()) + ); + + return; + } catch (NotFound $e) { Console::error($e->getMessage()); From 9f82cd78fb41256d24f4fb899fcd619e68e6f4d8 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 13:20:08 +0200 Subject: [PATCH 282/340] Update available --- src/Appwrite/Platform/Workers/Databases.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index fb13de3941..e913dfb350 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -281,11 +281,10 @@ class Databases extends Action } catch (DatabaseException\Dependency $e) { Console::error($e->getMessage()); - $dbForProject->updateDocument( - 'attributes', - $attribute->getId(), - $attribute->setAttribute('error', $e->getMessage()) - ); + $attribute->setAttribute('status', 'available'); + $attribute->setAttribute('error', $e->getMessage()); + + $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute); return; From 6067fb77b704f03ea505ee8b0d283ee36dec0242 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 13:40:41 +0200 Subject: [PATCH 283/340] Return on Dependency --- src/Appwrite/Platform/Workers/Databases.php | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index e913dfb350..aa2a189902 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -14,6 +14,7 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; +use Utopia\Database\Exception\Dependency; use Utopia\Database\Query; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -278,16 +279,6 @@ class Databases extends Action $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } - } catch (DatabaseException\Dependency $e) { - Console::error($e->getMessage()); - - $attribute->setAttribute('status', 'available'); - $attribute->setAttribute('error', $e->getMessage()); - - $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute); - - return; - } catch (NotFound $e) { Console::error($e->getMessage()); @@ -319,6 +310,10 @@ class Databases extends Action ); } + if ($e instanceof Dependency) { + return; + } + throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); From a3bd26d7f53a10482227bfc7e899b90cb74409c2 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 13:45:48 +0200 Subject: [PATCH 284/340] Return on Dependency --- src/Appwrite/Platform/Workers/Databases.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index aa2a189902..d26cdfcefd 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -293,16 +293,18 @@ class Databases extends Action if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (!$relatedAttribute->isEmpty()) { + if (! $relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } + $dbForProject->updateDocument( 'attributes', $attribute->getId(), $attribute->setAttribute('status', 'stuck') ); - if (!$relatedAttribute->isEmpty()) { + + if (! $relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), From cee3da2ef5c1751fe4a596910a634b1600b71d57 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 13:55:18 +0200 Subject: [PATCH 285/340] Remove previous --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 7772b91c1c..8c7292410d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -810,7 +810,7 @@ App::error() $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Dependency': - $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, $error->getMessage(), previous: $error); + $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY); break; } From 098c30cd9a4c7d64f4dc8254ceb8d6c47346d8f4 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 14:02:30 +0200 Subject: [PATCH 286/340] Message null --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 8c7292410d..7c30d61555 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -810,7 +810,7 @@ App::error() $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Dependency': - $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY); + $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error); break; } From c4bdd2fe1b12499c5d2970b37b2781812f4681dd Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 16:26:57 +0200 Subject: [PATCH 287/340] Change to 409 --- app/config/errors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/errors.php b/app/config/errors.php index ae1aae01c4..c1174509ab 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -734,7 +734,7 @@ return [ Exception::INDEX_DEPENDENCY => [ 'name' => Exception::INDEX_DEPENDENCY, 'description' => 'Attribute cannot be renamed or deleted. Please remove the associated index first.', - 'code' => 400, + 'code' => 409, ], /** Project Errors */ From 2ca690ccbdf3a76ac4e9ba339bc0e3337ea2f412 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Wed, 15 Jan 2025 16:29:17 +0200 Subject: [PATCH 288/340] formatting --- src/Appwrite/Platform/Workers/Databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index d26cdfcefd..ea2b6a2b73 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -11,10 +11,10 @@ use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\Dependency; use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; -use Utopia\Database\Exception\Dependency; use Utopia\Database\Query; use Utopia\Logger\Log; use Utopia\Platform\Action; From b16b662a21c3b4c11d19f8034c2e513bc4cbfe41 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:53:38 +0000 Subject: [PATCH 289/340] debug: log usage --- src/Appwrite/Event/Usage.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index 89e900d2ab..a09b651da8 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -2,6 +2,7 @@ namespace Appwrite\Event; +use Utopia\CLI\Console; use Utopia\Database\Document; use Utopia\Queue\Client; use Utopia\Queue\Connection; @@ -62,6 +63,11 @@ class Usage extends Event return false; } + Console::log('------------------------'); + Console::log('Usage Event Triggered'); + Console::log('Metrics: ' . json_encode($this->metrics, JSON_PRETTY_PRINT)); + Console::log('------------------------'); + $client = new Client($this->queue, $this->connection); $result = $client->enqueue([ From 120ceeedadc054ea08d095e7643049881d864eb0 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 16 Jan 2025 04:27:25 +0000 Subject: [PATCH 290/340] chore: review --- app/controllers/api/teams.php | 4 ++-- tests/e2e/Services/Teams/TeamsBaseClient.php | 5 +---- tests/e2e/Services/Teams/TeamsBaseServer.php | 5 +---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index feb1cb4acd..39dc2868de 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -547,8 +547,8 @@ App::post('/v1/teams/:teamId/memberships') } $membership = $dbForProject->findOne('memberships', [ - Query::equal('userId', [$invitee->getId()]), - Query::equal('teamId', [$team->getId()]), + Query::equal('userId', [$invitee->getInternalId()]), + Query::equal('teamId', [$team->getInternalId()]), ]); if ($membership->isEmpty()) { diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index cf011d2bf7..3381b80120 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -291,10 +291,7 @@ trait TeamsBaseClient $this->assertEquals($secondName, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - /** - * Test for resend - * SUCCESS - */ + // test for resending invitation $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 226536c604..bade16cf2f 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -185,10 +185,7 @@ trait TeamsBaseServer // $this->assertContains('team:'.$teamUid.'/admin', $response['body']['roles']); // $this->assertContains('team:'.$teamUid.'/editor', $response['body']['roles']); - /** - * Test for resend - * SUCCESS - */ + // test for resending invitation $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], From 23d20b7d02be0fa492d476d6cb90b57912391b98 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 16 Jan 2025 04:29:11 +0000 Subject: [PATCH 291/340] fix: invited user's name --- app/controllers/api/teams.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 39dc2868de..12b36b1e1b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -660,7 +660,7 @@ App::post('/v1/teams/:teamId/memberships') 'owner' => $user->getAttribute('name'), 'direction' => $locale->getText('settings.direction'), /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ - 'user' => $user->getAttribute('name'), + 'user' => $name, 'team' => $team->getAttribute('name'), 'redirect' => $url, 'project' => $projectName From de6fced412c8451d9ee2f2aaf1315cbb50f63a32 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 16 Jan 2025 11:35:22 +0530 Subject: [PATCH 292/340] feat: optimise events payloads --- composer.lock | 32 ++++++++++---------- src/Appwrite/Event/Event.php | 5 ++- src/Appwrite/Event/Webhook.php | 6 +--- src/Appwrite/Platform/Workers/Builds.php | 7 +++-- src/Appwrite/Platform/Workers/Databases.php | 7 +++-- src/Appwrite/Platform/Workers/Deletes.php | 8 ++--- src/Appwrite/Platform/Workers/Messaging.php | 6 ++-- src/Appwrite/Platform/Workers/Migrations.php | 6 ++-- src/Appwrite/Platform/Workers/Usage.php | 10 +++--- src/Appwrite/Platform/Workers/UsageDump.php | 17 +---------- src/Appwrite/Platform/Workers/Webhooks.php | 8 ++--- 11 files changed, 50 insertions(+), 62 deletions(-) diff --git a/composer.lock b/composer.lock index b77915f0a4..e5c79ee1dc 100644 --- a/composer.lock +++ b/composer.lock @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-30T11:49:49+00:00" + "time": "2025-01-15T23:07:07+00:00" }, { "name": "open-telemetry/sdk", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.2" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-01-15T05:56:26+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2025-01-14T16:20:53+00:00" }, { "name": "matthiasmullie/minify", diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index e3a2e394cf..a830fd66b1 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -136,7 +136,10 @@ class Event */ public function setProject(Document $project): self { - $this->project = $project; + $this->project = new Document([ + '$id' => $project->getId(), + '$internalId' => $project->getInternalId() + ]); return $this; } diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 36c6923cae..052d8f0fb9 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -20,11 +20,7 @@ class Webhook extends Event { /** Filter out context and trim project to keep the payload small */ $this->context = []; - $this->project = new Document([ - '$id' => $this->project->getId(), - '$internalId' => $this->project->getInternalId(), - ]); - + return parent::trigger(); } } diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index bef78a7514..4f5d6eb694 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -46,6 +46,7 @@ class Builds extends Action $this ->desc('Builds worker') ->inject('message') + ->inject('project') ->inject('dbForPlatform') ->inject('queueForEvents') ->inject('queueForFunctions') @@ -54,11 +55,12 @@ class Builds extends Action ->inject('dbForProject') ->inject('deviceForFunctions') ->inject('log') - ->callback(fn ($message, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log) => $this->action($message, $dbForPlatform, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log)); + ->callback(fn ($message, Document $project, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log) => $this->action($message, $project, $dbForPlatform, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log)); } /** * @param Message $message + * @param Document $project * @param Database $dbForPlatform * @param Event $queueForEvents * @param Func $queueForFunctions @@ -70,7 +72,7 @@ class Builds extends Action * @return void * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $queueForUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Event $queueForEvents, Func $queueForFunctions, Usage $queueForUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log): void { $payload = $message->getPayload() ?? []; @@ -79,7 +81,6 @@ class Builds extends Action } $type = $payload['type'] ?? ''; - $project = new Document($payload['project'] ?? []); $resource = new Document($payload['resource'] ?? []); $deployment = new Document($payload['deployment'] ?? []); $template = new Document($payload['template'] ?? []); diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 5b73e6a75c..9345f31165 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -34,21 +34,23 @@ class Databases extends Action $this ->desc('Databases worker') ->inject('message') + ->inject('project') ->inject('dbForPlatform') ->inject('dbForProject') ->inject('log') - ->callback(fn (Message $message, Database $dbForPlatform, Database $dbForProject, Log $log) => $this->action($message, $dbForPlatform, $dbForProject, $log)); + ->callback(fn (Message $message, Document $project, Database $dbForPlatform, Database $dbForProject, Log $log) => $this->action($message, $project, $dbForPlatform, $dbForProject, $log)); } /** * @param Message $message + * @param Document $project * @param Database $dbForPlatform * @param Database $dbForProject * @param Log $log * @return void * @throws \Exception */ - public function action(Message $message, Database $dbForPlatform, Database $dbForProject, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Database $dbForProject, Log $log): void { $payload = $message->getPayload() ?? []; @@ -57,7 +59,6 @@ class Databases extends Action } $type = $payload['type']; - $project = new Document($payload['project']); $collection = new Document($payload['collection'] ?? []); $document = new Document($payload['document'] ?? []); $database = new Document($payload['database'] ?? []); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 9aaf19f412..35ee50c791 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -43,6 +43,7 @@ class Deletes extends Action $this ->desc('Deletes worker') ->inject('message') + ->inject('project') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('timelimit') @@ -55,8 +56,8 @@ class Deletes extends Action ->inject('auditRetention') ->inject('log') ->callback( - fn ($message, $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executionRetention, $auditRetention, $log) + fn ($message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log) => + $this->action($message, $project, $dbForPlatform, $getProjectDB, $timelimit, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executionRetention, $auditRetention, $log) ); } @@ -64,7 +65,7 @@ class Deletes extends Action * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $timelimit, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log): void { $payload = $message->getPayload() ?? []; @@ -78,7 +79,6 @@ class Deletes extends Action $resource = $payload['resource'] ?? null; $resourceType = $payload['resourceType'] ?? null; $document = new Document($payload['document'] ?? []); - $project = new Document($payload['project'] ?? []); $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 1ff032c3e1..febc4a4e55 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -58,15 +58,17 @@ class Messaging extends Action $this ->desc('Messaging worker') ->inject('message') + ->inject('project') ->inject('log') ->inject('dbForProject') ->inject('deviceForFiles') ->inject('queueForUsage') - ->callback(fn (Message $message, Log $log, Database $dbForProject, Device $deviceForFiles, Usage $queueForUsage) => $this->action($message, $log, $dbForProject, $deviceForFiles, $queueForUsage)); + ->callback(fn (Message $message, Document $project, Log $log, Database $dbForProject, Device $deviceForFiles, Usage $queueForUsage) => $this->action($message, $project, $log, $dbForProject, $deviceForFiles, $queueForUsage)); } /** * @param Message $message + * @param Document $project * @param Log $log * @param Database $dbForProject * @param Device $deviceForFiles @@ -76,6 +78,7 @@ class Messaging extends Action */ public function action( Message $message, + Document $project, Log $log, Database $dbForProject, Device $deviceForFiles, @@ -89,7 +92,6 @@ class Messaging extends Action } $type = $payload['type'] ?? ''; - $project = new Document($payload['project'] ?? []); switch ($type) { case MESSAGE_SEND_TYPE_INTERNAL: diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index f6af0eb5f2..078c9fa0ff 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -51,16 +51,17 @@ class Migrations extends Action $this ->desc('Migrations worker') ->inject('message') + ->inject('project') ->inject('dbForProject') ->inject('dbForPlatform') ->inject('logError') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForPlatform, callable $logError) => $this->action($message, $dbForProject, $dbForPlatform, $logError)); + ->callback(fn (Message $message, Document $project, Database $dbForProject, Database $dbForPlatform, callable $logError) => $this->action($message, $project, $dbForProject, $dbForPlatform, $logError)); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForPlatform, callable $logError): void + public function action(Message $message, Document $project, Database $dbForProject, Database $dbForPlatform, callable $logError): void { $payload = $message->getPayload() ?? []; @@ -69,7 +70,6 @@ class Migrations extends Action } $events = $payload['events'] ?? []; - $project = new Document($payload['project'] ?? []); $migration = new Document($payload['migration'] ?? []); if ($project->getId() === 'console') { diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 8199fe73a7..be916f33e9 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -34,10 +34,11 @@ class Usage extends Action $this ->desc('Usage worker') ->inject('message') + ->inject('project') ->inject('getProjectDB') ->inject('queueForUsageDump') - ->callback(function (Message $message, callable $getProjectDB, UsageDump $queueForUsageDump) { - $this->action($message, $getProjectDB, $queueForUsageDump); + ->callback(function (Message $message, Document $project, callable $getProjectDB, UsageDump $queueForUsageDump) { + $this->action($message, $project, $getProjectDB, $queueForUsageDump); }); $this->aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); @@ -46,21 +47,20 @@ class Usage extends Action /** * @param Message $message + * @param Document $project * @param callable $getProjectDB * @param UsageDump $queueForUsageDump * @return void * @throws \Utopia\Database\Exception * @throws Exception */ - public function action(Message $message, callable $getProjectDB, UsageDump $queueForUsageDump): void + public function action(Message $message, Document $project, callable $getProjectDB, UsageDump $queueForUsageDump): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { throw new Exception('Missing payload'); } - $document = $payload['project'] ?? []; - $project = new Document($document); if (empty($project->getAttribute('database'))) { var_dump($payload); diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 3e50ba0363..2f1d13f29a 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -59,26 +59,11 @@ class UsageDump extends Action foreach ($payload['stats'] ?? [] as $stats) { - //$project = new Document($stats['project'] ?? []); - - /** - * Start temp bug fallback - */ - $document = $stats['project'] ?? []; - if (!empty($document['$uid'])) { - $document['$id'] = $document['$uid']; - } - - $project = new Document($document); - - if (empty($project->getAttribute('database'))) { - continue; - } + $project = new Document($stats['project'] ?? []); /** * End temp bug fallback */ - $numberOfKeys = !empty($stats['keys']) ? count($stats['keys']) : 0; $receivedAt = $stats['receivedAt'] ?? 'NONE'; if ($numberOfKeys === 0) { diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 50f64ea02d..a76e4f17b0 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -32,22 +32,24 @@ class Webhooks extends Action $this ->desc('Webhooks worker') ->inject('message') + ->inject('project') ->inject('dbForPlatform') ->inject('queueForMails') ->inject('queueForUsage') ->inject('log') - ->callback(fn (Message $message, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log) => $this->action($message, $dbForPlatform, $queueForMails, $queueForUsage, $log)); + ->callback(fn (Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log) => $this->action($message, $project, $dbForPlatform, $queueForMails, $queueForUsage, $log)); } /** * @param Message $message + * @param Document $project * @param Database $dbForPlatform * @param Mail $queueForMails * @param Log $log * @return void * @throws Exception */ - public function action(Message $message, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, Usage $queueForUsage, Log $log): void { $this->errors = []; $payload = $message->getPayload() ?? []; @@ -60,8 +62,6 @@ class Webhooks extends Action $webhookPayload = json_encode($payload['payload']); $user = new Document($payload['user'] ?? []); - $project = new Document($payload['project']); - $project = $dbForPlatform->getDocument('projects', $project->getId()); $log->addTag('projectId', $project->getId()); foreach ($project->getAttribute('webhooks', []) as $webhook) { From 8ea1f436c1dd501b6d5b6469ab18d6b453e9f6a8 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 16 Jan 2025 11:37:02 +0530 Subject: [PATCH 293/340] feat: linter --- src/Appwrite/Event/Webhook.php | 3 +-- src/Appwrite/Platform/Workers/Usage.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 052d8f0fb9..c7035070b8 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -2,7 +2,6 @@ namespace Appwrite\Event; -use Utopia\Database\Document; use Utopia\Queue\Connection; class Webhook extends Event @@ -20,7 +19,7 @@ class Webhook extends Event { /** Filter out context and trim project to keep the payload small */ $this->context = []; - + return parent::trigger(); } } diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index be916f33e9..3687eeab67 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -34,7 +34,7 @@ class Usage extends Action $this ->desc('Usage worker') ->inject('message') - ->inject('project') + ->inject('project') ->inject('getProjectDB') ->inject('queueForUsageDump') ->callback(function (Message $message, Document $project, callable $getProjectDB, UsageDump $queueForUsageDump) { From 8dc3b4ca6032c337e7f0e9a0f6b078d90a38e83f Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 16 Jan 2025 06:15:41 +0000 Subject: [PATCH 294/340] fix: tests: --- app/controllers/api/teams.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 12b36b1e1b..827ca58964 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -547,8 +547,8 @@ App::post('/v1/teams/:teamId/memberships') } $membership = $dbForProject->findOne('memberships', [ - Query::equal('userId', [$invitee->getInternalId()]), - Query::equal('teamId', [$team->getInternalId()]), + Query::equal('userInternalId', [$invitee->getInternalId()]), + Query::equal('teamInternalId', [$team->getInternalId()]), ]); if ($membership->isEmpty()) { From 8e474676d3a9f5080d3b080cd7b477578c555238 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 16 Jan 2025 06:36:31 +0000 Subject: [PATCH 295/340] chore: explicitly added token --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fc03891b35..7fcd83ce57 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -243,6 +243,7 @@ jobs: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' body-includes: Benchmark results + token: ${{ secrets.GITHUB_TOKEN }} - name: Comment on PR uses: peter-evans/create-or-update-comment@v4 with: @@ -250,3 +251,4 @@ jobs: issue-number: ${{ github.event.pull_request.number }} body-path: benchmark.txt edit-mode: replace + token: ${{ secrets.GITHUB_TOKEN }} From e278b8a5a2e6ee04938ab400819dd7923fe31866 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 16 Jan 2025 07:35:43 +0000 Subject: [PATCH 296/340] chore: added if check --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7fcd83ce57..5b7438de42 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -237,18 +237,18 @@ jobs: path: benchmark.json retention-days: 7 - name: Find Comment + if: github.event.pull_request.head.repo.full_name == github.repository uses: peter-evans/find-comment@v3 id: fc with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' body-includes: Benchmark results - token: ${{ secrets.GITHUB_TOKEN }} - name: Comment on PR + if: github.event.pull_request.head.repo.full_name == github.repository uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body-path: benchmark.txt - edit-mode: replace - token: ${{ secrets.GITHUB_TOKEN }} + edit-mode: replace \ No newline at end of file From e8f97baf262531bf45020a082302103fc2091383 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 16 Jan 2025 13:14:47 +0530 Subject: [PATCH 297/340] fix: incorrect project payloads --- app/init.php | 1 + src/Appwrite/Event/Audit.php | 2 + src/Appwrite/Event/Build.php | 2 + src/Appwrite/Event/Certificate.php | 2 + src/Appwrite/Event/Database.php | 2 + src/Appwrite/Event/Delete.php | 2 + src/Appwrite/Event/Event.php | 18 ++++++++- src/Appwrite/Event/Func.php | 2 + src/Appwrite/Event/Mail.php | 2 + src/Appwrite/Event/Messaging.php | 2 + src/Appwrite/Event/Migration.php | 2 + src/Appwrite/Event/Usage.php | 4 +- src/Appwrite/Event/UsageDump.php | 2 + src/Appwrite/Event/Webhook.php | 1 - src/Appwrite/Platform/Tasks/Maintenance.php | 44 ++------------------- src/Appwrite/Platform/Workers/Deletes.php | 12 ++++++ 16 files changed, 55 insertions(+), 45 deletions(-) diff --git a/app/init.php b/app/init.php index df2a66aa00..df0e9d3a08 100644 --- a/app/init.php +++ b/app/init.php @@ -202,6 +202,7 @@ const DELETE_TYPE_TOPIC = 'topic'; const DELETE_TYPE_TARGET = 'target'; const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets'; const DELETE_TYPE_SESSION_TARGETS = 'session_targets'; +const DELETE_TYPE_MAINTENANCE = 'maintenance'; // Message types const MESSAGE_SEND_TYPE_INTERNAL = 'internal'; diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 406f64b370..5cbe379666 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -150,6 +150,8 @@ class Audit extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 1fbf20a9f9..bdbcf6826c 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -116,6 +116,8 @@ class Build extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Certificate.php b/src/Appwrite/Event/Certificate.php index 5d30c3d5ac..2629653c59 100644 --- a/src/Appwrite/Event/Certificate.php +++ b/src/Appwrite/Event/Certificate.php @@ -78,6 +78,8 @@ class Certificate extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 1b0ea6851c..e78fe967e7 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -121,6 +121,8 @@ class Database extends Event $this->setQueue($dsn->getHost()); + $this->trimFields(); + $client = new Client($this->queue, $this->connection); try { diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 1a4c9318e3..2874043163 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -144,6 +144,8 @@ class Delete extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index a830fd66b1..4029502ea7 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -135,10 +135,22 @@ class Event * @return self */ public function setProject(Document $project): self + { + $this->project = $project; + return $this; + } + + /** + * Trims the fields of the project document to only include the necessary fields. + * + * @return self + */ + public function trimFields(): self { $this->project = new Document([ - '$id' => $project->getId(), - '$internalId' => $project->getInternalId() + '$id' => $this->project->getId(), + '$internalId' => $this->project->getInternalId(), + 'database' => $this->project->getAttribute('database') ]); return $this; @@ -327,6 +339,8 @@ class Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 0ad639a9f5..7c6a2e9194 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -217,6 +217,8 @@ class Func extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); $events = $this->getEvent() ? Event::generateEvents($this->getEvent(), $this->getParams()) : null; diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index a0fca75688..0db576ba68 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -408,6 +408,8 @@ class Mail extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index 755b8c9158..ac2df7f92a 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -186,6 +186,8 @@ class Messaging extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index 789b8e2160..376264bce3 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -79,6 +79,8 @@ class Migration extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index 89e900d2ab..f17c048a2e 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -62,10 +62,12 @@ class Usage extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); $result = $client->enqueue([ - 'project' => $this->getProject(), + 'project' => $this->project, 'reduce' => $this->reduce, 'metrics' => $this->metrics, ]); diff --git a/src/Appwrite/Event/UsageDump.php b/src/Appwrite/Event/UsageDump.php index 2998e4e104..83206e4add 100644 --- a/src/Appwrite/Event/UsageDump.php +++ b/src/Appwrite/Event/UsageDump.php @@ -42,6 +42,8 @@ class UsageDump extends Event return false; } + $this->trimFields(); + $client = new Client($this->queue, $this->connection); return $client->enqueue([ diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index c7035070b8..9d14dcdc3d 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -19,7 +19,6 @@ class Webhook extends Event { /** Filter out context and trim project to keep the payload small */ $this->context = []; - return parent::trigger(); } } diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index c789cbdaac..a7558934b5 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -64,11 +64,9 @@ class Maintenance extends Action */ protected function notifyProjects(Delete $queueForDeletes, int $usageStatsRetentionHourly): void { - $this->notifyDeleteTargets($queueForDeletes); - $this->notifyDeleteExecutionLogs($queueForDeletes); - $this->notifyDeleteAuditLogs($queueForDeletes); - $this->notifyDeleteUsageStats($usageStatsRetentionHourly, $queueForDeletes); - $this->notifyDeleteExpiredSessions($queueForDeletes); + $queueForDeletes + ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->trigger(); } protected function foreachProject(Database $dbForPlatform, callable $callback): void @@ -98,28 +96,6 @@ class Maintenance extends Action Console::info("Found {$count} projects " . ($executionEnd - $executionStart) . " seconds"); } - private function notifyDeleteExecutionLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_EXECUTIONS) - ->trigger(); - } - - private function notifyDeleteAuditLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_AUDIT) - ->trigger(); - } - - private function notifyDeleteUsageStats(int $usageStatsRetentionHourly, Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_USAGE) - ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) - ->trigger(); - } - private function notifyDeleteConnections(Delete $queueForDeletes): void { $queueForDeletes @@ -128,13 +104,6 @@ class Maintenance extends Action ->trigger(); } - private function notifyDeleteExpiredSessions(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_SESSIONS) - ->trigger(); - } - private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void { $time = DateTime::now(); @@ -177,11 +146,4 @@ class Maintenance extends Action ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) ->trigger(); } - - private function notifyDeleteTargets(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_EXPIRED_TARGETS) - ->trigger(); - } } diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 35ee50c791..45e7725c9b 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -153,11 +153,23 @@ class Deletes extends Action case DELETE_TYPE_SESSION_TARGETS: $this->deleteSessionTargets($project, $getProjectDB, $document); break; + case DELETE_TYPE_MAINTENANCE: + $this->performMaintenance($project, $getProjectDB, $executionRetention, $auditRetention, $hourlyUsageRetentionDatetime); + break; default: throw new \Exception('No delete operation for type: ' . \strval($type)); } } + private function performMaintenance(Document $project, callable $getProjectDB, string $executionRetention, string $auditRetention, string $hourlyUsageRetentionDatetime): void + { + $this->deleteExpiredTargets($project, $getProjectDB); + $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); + $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); + $this->deleteUsageStats($project, $getProjectDB, $hourlyUsageRetentionDatetime); + $this->deleteExpiredSessions($project, $getProjectDB); + } + /** * @param Database $dbForPlatform * @param callable $getProjectDB From 2a0894f3d1df1015f3a7d2f5acc04cccbb4b2096 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 16 Jan 2025 13:29:08 +0530 Subject: [PATCH 298/340] fix: incorrect project payloads --- src/Appwrite/Event/Event.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 4029502ea7..4efc138ec6 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -147,11 +147,13 @@ class Event */ public function trimFields(): self { - $this->project = new Document([ - '$id' => $this->project->getId(), - '$internalId' => $this->project->getInternalId(), - 'database' => $this->project->getAttribute('database') - ]); + if ($this->project) { + $this->project = new Document([ + '$id' => $this->project->getId(), + '$internalId' => $this->project->getInternalId(), + 'database' => $this->project->getAttribute('database') + ]); + } return $this; } From f52b2d5dcde55de4928740371e6d39b5dce0262a Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Thu, 16 Jan 2025 16:59:30 +0530 Subject: [PATCH 299/340] chore: review comments --- src/Appwrite/Platform/Workers/Deletes.php | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 45e7725c9b..539bbd61f9 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -154,22 +154,17 @@ class Deletes extends Action $this->deleteSessionTargets($project, $getProjectDB, $document); break; case DELETE_TYPE_MAINTENANCE: - $this->performMaintenance($project, $getProjectDB, $executionRetention, $auditRetention, $hourlyUsageRetentionDatetime); + $this->deleteExpiredTargets($project, $getProjectDB); + $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); + $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); + $this->deleteUsageStats($project, $getProjectDB, $hourlyUsageRetentionDatetime); + $this->deleteExpiredSessions($project, $getProjectDB); break; default: throw new \Exception('No delete operation for type: ' . \strval($type)); } } - private function performMaintenance(Document $project, callable $getProjectDB, string $executionRetention, string $auditRetention, string $hourlyUsageRetentionDatetime): void - { - $this->deleteExpiredTargets($project, $getProjectDB); - $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); - $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); - $this->deleteUsageStats($project, $getProjectDB, $hourlyUsageRetentionDatetime); - $this->deleteExpiredSessions($project, $getProjectDB); - } - /** * @param Database $dbForPlatform * @param callable $getProjectDB From 0afbfe2f84bb7d0ffec49b853592874ea1e567f1 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 16 Jan 2025 17:20:30 +0200 Subject: [PATCH 300/340] INDEX_DEPENDENCY --- app/controllers/api/databases.php | 13 ++++++ composer.json | 2 +- composer.lock | 71 +++++++++++++++++-------------- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 347b4ebbef..22282a8799 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -36,6 +36,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Index as IndexValidator; +use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Queries; @@ -2421,6 +2422,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } + /** + * Check index dependency + */ + $validator = new IndexDependencyValidator( + $collection->getAttribute('indexes'), + $dbForProject->getAdapter()->getSupportForCastIndexArray(), + ); + + if (! $validator->isValid($attribute)) { + throw new Exception(Exception::INDEX_DEPENDENCY, $validator->getDescription()); + } + // Only update status if removing available attribute if ($attribute->getAttribute('status') === 'available') { $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); diff --git a/composer.json b/composer.json index 882be5b94e..aecb6e0b7e 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.32", + "utopia-php/database": "dev-calculate-row-size as 0.53.32", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index b77915f0a4..18470a2f10 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": "c88950f1d3119d0764a469e1d804ce71", + "content-hash": "2660c24c56f07ac34e51d6128fa67557", "packages": [ { "name": "adhocore/jwt", @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-30T11:49:49+00:00" + "time": "2025-01-15T23:07:07+00:00" }, { "name": "open-telemetry/sdk", @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.32", + "version": "dev-calculate-row-size", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "981a1241139b42dccd531511130b79137740b205" + "reference": "7f433be4596ae3fce0af98e5a02c446aeaff19f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205", - "reference": "981a1241139b42dccd531511130b79137740b205", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7f433be4596ae3fce0af98e5a02c446aeaff19f2", + "reference": "7f433be4596ae3fce0af98e5a02c446aeaff19f2", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.32" + "source": "https://github.com/utopia-php/database/tree/calculate-row-size" }, - "time": "2025-01-10T08:53:47+00:00" + "time": "2025-01-16T14:43:10+00:00" }, { "name": "utopia-php/domains", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.2" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-01-15T05:56:26+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2025-01-14T16:20:53+00:00" }, { "name": "matthiasmullie/minify", @@ -8554,9 +8554,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-calculate-row-size", + "alias": "0.53.32", + "alias_normalized": "0.53.32.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From 1b4a96b1fbe99d96640755caf64903b484ae009a Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 16 Jan 2025 17:22:53 +0200 Subject: [PATCH 301/340] Remove code from worker --- src/Appwrite/Platform/Workers/Databases.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index ea2b6a2b73..5b73e6a75c 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -11,7 +11,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; -use Utopia\Database\Exception\Dependency; use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; @@ -293,18 +292,16 @@ class Databases extends Action if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (! $relatedAttribute->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } - $dbForProject->updateDocument( 'attributes', $attribute->getId(), $attribute->setAttribute('status', 'stuck') ); - - if (! $relatedAttribute->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), @@ -312,10 +309,6 @@ class Databases extends Action ); } - if ($e instanceof Dependency) { - return; - } - throw $e; } finally { $this->trigger($database, $collection, $attribute, $project, $projectId, $events); From 13687f7fc3437795f74222b8872389fb864a8005 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Thu, 16 Jan 2025 17:33:51 +0200 Subject: [PATCH 302/340] Use 1.6.x --- app/controllers/api/databases.php | 2 +- composer.json | 2 +- composer.lock | 71 ++++++++++++++----------------- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 22282a8799..6798d71502 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2431,7 +2431,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ); if (! $validator->isValid($attribute)) { - throw new Exception(Exception::INDEX_DEPENDENCY, $validator->getDescription()); + throw new Exception(Exception::INDEX_DEPENDENCY); } // Only update status if removing available attribute diff --git a/composer.json b/composer.json index aecb6e0b7e..882be5b94e 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-calculate-row-size as 0.53.32", + "utopia-php/database": "0.53.32", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 18470a2f10..b77915f0a4 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": "2660c24c56f07ac34e51d6128fa67557", + "content-hash": "c88950f1d3119d0764a469e1d804ce71", "packages": [ { "name": "adhocore/jwt", @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.5.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", - "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", + "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-01-15T23:07:07+00:00" + "time": "2024-10-30T11:49:49+00:00" }, { "name": "open-telemetry/sdk", @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.3", + "version": "0.1.2", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "66f093557ba66d98245e562036182016c7dcfe8a" + "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", - "reference": "66f093557ba66d98245e562036182016c7dcfe8a", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", + "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.3" + "source": "https://github.com/utopia-php/compression/tree/0.1.2" }, - "time": "2025-01-15T15:15:51+00:00" + "time": "2024-11-08T14:59:54+00:00" }, { "name": "utopia-php/config", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "dev-calculate-row-size", + "version": "0.53.32", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "7f433be4596ae3fce0af98e5a02c446aeaff19f2" + "reference": "981a1241139b42dccd531511130b79137740b205" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/7f433be4596ae3fce0af98e5a02c446aeaff19f2", - "reference": "7f433be4596ae3fce0af98e5a02c446aeaff19f2", + "url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205", + "reference": "981a1241139b42dccd531511130b79137740b205", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/calculate-row-size" + "source": "https://github.com/utopia-php/database/tree/0.53.32" }, - "time": "2025-01-16T14:43:10+00:00" + "time": "2025-01-10T08:53:47+00:00" }, { "name": "utopia-php/domains", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.2", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2025-01-15T05:56:26+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.20.0", + "version": "v1.19.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-01-14T16:20:53+00:00" + "time": "2024-12-30T16:20:10+00:00" }, { "name": "matthiasmullie/minify", @@ -8554,18 +8554,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-calculate-row-size", - "alias": "0.53.32", - "alias_normalized": "0.53.32.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From f392b5ab45c8087c1a5065c8b37f33fffea8d7ee Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:01:35 +0000 Subject: [PATCH 303/340] chore: composer update --- composer.lock | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/composer.lock b/composer.lock index b77915f0a4..57a5d9294a 100644 --- a/composer.lock +++ b/composer.lock @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-30T11:49:49+00:00" + "time": "2025-01-15T23:07:07+00:00" }, { "name": "open-telemetry/sdk", @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -3678,16 +3678,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.15", + "version": "0.33.16", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", + "url": "https://api.github.com/repos/utopia-php/http/zipball/e91d4c560d1b809e25faa63d564fef034363b50f", + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f", "shasum": "" }, "require": { @@ -3719,9 +3719,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.15" + "source": "https://github.com/utopia-php/http/tree/0.33.16" }, - "time": "2024-12-10T13:07:04+00:00" + "time": "2025-01-16T15:58:50+00:00" }, { "name": "utopia-php/image", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.2", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.2" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-01-15T05:56:26+00:00" }, { "name": "utopia-php/pools", @@ -5126,16 +5126,16 @@ }, { "name": "laravel/pint", - "version": "v1.19.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", - "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", + "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-12-30T16:20:10+00:00" + "time": "2025-01-14T16:20:53+00:00" }, { "name": "matthiasmullie/minify", From 7db65f46ae0fe5b0646688b3e9af6487d94eed64 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:23:22 +0000 Subject: [PATCH 304/340] feat: add compression toggle env --- app/http.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/http.php b/app/http.php index 3a7562ffd1..dac941d25b 100644 --- a/app/http.php +++ b/app/http.php @@ -334,7 +334,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool } $app = new App('UTC'); - $app->setCompression(true); + $app->setCompression(System::getEnv('_APP_COMPRESSION_ENABLED', 'enabled') === 'enabled'); $app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB $pools = $register->get('pools'); From facdf1a362ed6a08afdfa0b7f6c45270c1b14965 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:05:49 +0000 Subject: [PATCH 305/340] chore: revert usage debug --- src/Appwrite/Event/Usage.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index a09b651da8..89e900d2ab 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -2,7 +2,6 @@ namespace Appwrite\Event; -use Utopia\CLI\Console; use Utopia\Database\Document; use Utopia\Queue\Client; use Utopia\Queue\Connection; @@ -63,11 +62,6 @@ class Usage extends Event return false; } - Console::log('------------------------'); - Console::log('Usage Event Triggered'); - Console::log('Metrics: ' . json_encode($this->metrics, JSON_PRETTY_PRINT)); - Console::log('------------------------'); - $client = new Client($this->queue, $this->connection); $result = $client->enqueue([ From a1031ab921ec2b2ceb876fc194e2adcabf43b13b Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Fri, 17 Jan 2025 03:58:23 +0000 Subject: [PATCH 306/340] fix: update membership --- app/controllers/api/teams.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 827ca58964..7efe2a5a2d 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -582,6 +582,12 @@ App::post('/v1/teams/:teamId/memberships') Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } else { + $membership = new Document([ + '$id' => $membership->getId(), + 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, + 'confirm' => ($isPrivilegedUser || $isAppUser), + ]); + $membership = ($isPrivilegedUser || $isAppUser) ? Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); From 95dcb67747922d3f640974c0c164308019535806 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Fri, 17 Jan 2025 13:31:39 +0900 Subject: [PATCH 307/340] Implement new SDK Class on 1.6.x --- app/config/specs/open-api3-latest-client.json | 300 +---- .../specs/open-api3-latest-console.json | 1143 +--------------- app/config/specs/open-api3-latest-server.json | 830 +----------- app/config/specs/swagger2-latest-client.json | 304 +---- app/config/specs/swagger2-latest-console.json | 1195 +---------------- app/config/specs/swagger2-latest-server.json | 879 +----------- app/controllers/api/account.php | 998 +++++++++----- app/controllers/api/avatars.php | 154 ++- app/controllers/api/console.php | 45 +- app/controllers/api/databases.php | 971 +++++++++----- app/controllers/api/functions.php | 552 +++++--- app/controllers/api/graphql.php | 80 +- app/controllers/api/health.php | 469 ++++--- app/controllers/api/locale.php | 173 ++- app/controllers/api/messaging.php | 884 +++++++----- app/controllers/api/migrations.php | 242 ++-- app/controllers/api/project.php | 119 +- app/controllers/api/projects.php | 835 ++++++++---- app/controllers/api/proxy.php | 98 +- app/controllers/api/storage.php | 300 +++-- app/controllers/api/teams.php | 282 ++-- app/controllers/api/users.php | 824 ++++++++---- app/controllers/api/vcs.php | 216 +-- app/controllers/general.php | 34 +- app/controllers/mock.php | 4 +- app/controllers/shared/api.php | 17 +- composer.lock | 34 +- src/Appwrite/GraphQL/Schema.php | 45 +- src/Appwrite/GraphQL/Types/Mapper.php | 43 +- src/Appwrite/Platform/Tasks/Specs.php | 92 +- src/Appwrite/SDK/AuthType.php | 11 + src/Appwrite/SDK/ContentType.php | 15 + src/Appwrite/SDK/Method.php | 276 ++++ src/Appwrite/SDK/MethodType.php | 11 + src/Appwrite/SDK/Response.php | 27 + .../Specification/Format/OpenAPI3.php | 216 +-- .../Specification/Format/Swagger2.php | 214 +-- src/Appwrite/Utopia/Request.php | 26 +- tests/unit/Utopia/RequestTest.php | 10 +- 39 files changed, 5671 insertions(+), 7297 deletions(-) create mode 100644 src/Appwrite/SDK/AuthType.php create mode 100644 src/Appwrite/SDK/ContentType.php create mode 100644 src/Appwrite/SDK/Method.php create mode 100644 src/Appwrite/SDK/MethodType.php create mode 100644 src/Appwrite/SDK/Response.php diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index af7303c985..4c82afc8a7 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -109,9 +106,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -196,9 +190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -274,9 +265,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -335,9 +323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -400,9 +385,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -451,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -519,9 +498,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -591,9 +567,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -659,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -739,9 +709,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -809,9 +776,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -857,10 +821,10 @@ ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -885,9 +849,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -963,9 +924,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1016,9 +974,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1067,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1118,9 +1070,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1171,9 +1120,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1243,9 +1189,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1320,9 +1263,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1398,9 +1338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1449,9 +1386,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1524,9 +1458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1600,9 +1531,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1684,9 +1612,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1728,9 +1653,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1781,9 +1703,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1832,9 +1751,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1908,9 +1824,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1977,9 +1890,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2120,9 +2030,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2196,9 +2103,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2272,9 +2176,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2335,9 +2236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2391,9 +2289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2456,9 +2351,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2508,9 +2400,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2589,9 +2478,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2643,14 +2529,7 @@ "description": "", "responses": { "204": { - "description": "No content", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { @@ -2669,9 +2548,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2733,9 +2609,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2817,9 +2690,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2896,9 +2766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3042,9 +2909,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3118,9 +2982,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3188,9 +3049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3269,9 +3127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3320,9 +3175,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3392,9 +3244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3520,9 +3369,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3652,9 +3498,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3712,9 +3555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4202,9 +4042,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4286,9 +4123,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4380,9 +4214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4481,9 +4312,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4568,9 +4396,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4677,9 +4502,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4774,9 +4596,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4875,9 +4694,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4961,9 +4777,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5049,9 +4862,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5166,9 +4976,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5242,9 +5049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5296,9 +5100,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5350,9 +5151,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5404,9 +5202,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5458,9 +5253,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5512,9 +5304,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5566,9 +5355,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5620,9 +5406,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5674,9 +5457,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5728,9 +5508,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5783,9 +5560,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5868,9 +5642,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5944,9 +5715,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6032,9 +5800,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6132,9 +5897,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6206,9 +5968,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6297,9 +6056,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6366,9 +6122,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6435,9 +6188,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6653,9 +6403,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6729,9 +6476,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6807,9 +6551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6894,9 +6635,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6958,9 +6696,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7034,9 +6769,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7100,9 +6832,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7188,9 +6917,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7301,9 +7027,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7375,9 +7098,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7464,9 +7184,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7539,9 +7256,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7639,9 +7353,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7702,9 +7413,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 28a242f6ad..fa0455e2ee 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -108,9 +105,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -185,9 +179,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -236,9 +227,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -313,9 +301,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -373,9 +358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -437,9 +419,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -488,9 +467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -555,9 +531,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -626,9 +599,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -693,9 +663,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -772,9 +739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -841,9 +805,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -889,10 +850,10 @@ ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -917,9 +878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -994,9 +952,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1046,9 +1001,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1096,9 +1048,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1146,9 +1095,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1198,9 +1144,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1269,9 +1212,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1345,9 +1285,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1422,9 +1359,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1472,9 +1406,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1546,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1621,9 +1549,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1704,9 +1629,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1747,9 +1669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1799,9 +1718,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1850,9 +1766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1926,9 +1839,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1995,9 +1905,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2138,9 +2045,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2214,9 +2118,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2290,9 +2191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2352,9 +2250,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2407,9 +2302,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2471,9 +2363,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2522,9 +2411,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2602,9 +2488,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2655,14 +2538,7 @@ "description": "", "responses": { "204": { - "description": "No content", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { @@ -2681,9 +2557,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2744,9 +2617,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2828,9 +2698,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2907,9 +2774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3053,9 +2917,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3129,9 +2990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3198,9 +3056,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3278,9 +3133,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3328,9 +3180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3399,9 +3248,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3527,9 +3373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3659,9 +3502,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3719,9 +3559,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4209,9 +4046,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4293,9 +4127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4387,9 +4218,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4479,9 +4307,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4548,9 +4373,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4598,9 +4420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4673,9 +4492,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4754,9 +4570,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4828,9 +4641,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4889,9 +4699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4967,9 +4774,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5030,9 +4834,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5115,9 +4916,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5221,9 +5019,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5292,9 +5087,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5393,9 +5185,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5466,9 +5255,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5552,9 +5338,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5636,7 +5419,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5660,9 +5443,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5773,9 +5553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5857,7 +5634,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5881,9 +5658,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5994,9 +5768,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6078,7 +5849,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -6102,9 +5873,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6215,9 +5983,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6308,7 +6073,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -6332,9 +6097,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6454,9 +6216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6548,7 +6307,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6572,9 +6331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6697,9 +6453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6791,7 +6544,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6815,9 +6568,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6940,9 +6690,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7024,7 +6771,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -7048,9 +6795,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7161,9 +6905,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7294,9 +7035,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7389,7 +7127,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -7413,9 +7151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7531,9 +7266,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7615,7 +7347,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7639,9 +7371,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7783,9 +7512,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7856,9 +7582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7914,7 +7637,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7938,9 +7661,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8050,9 +7770,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8137,9 +7854,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8246,9 +7960,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8343,9 +8054,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8444,9 +8152,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8528,9 +8233,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8623,9 +8325,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8707,9 +8406,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8829,9 +8525,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8902,9 +8595,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8984,9 +8674,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9069,9 +8756,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9163,9 +8847,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9238,9 +8919,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9322,9 +9000,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9397,9 +9072,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9646,9 +9318,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9698,9 +9367,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9749,9 +9415,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9851,9 +9514,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9913,9 +9573,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9987,9 +9644,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10048,9 +9702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10274,9 +9925,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10337,9 +9985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10422,9 +10067,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10520,9 +10162,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10591,9 +10230,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10655,9 +10291,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10721,9 +10354,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10808,9 +10438,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10875,9 +10502,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10951,9 +10575,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11039,9 +10660,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11156,9 +10774,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11221,9 +10836,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11294,9 +10906,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11378,9 +10987,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11439,9 +11045,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11527,9 +11130,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11598,9 +11198,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11686,9 +11283,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11761,9 +11355,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11815,9 +11406,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11867,9 +11455,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11918,9 +11503,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11969,9 +11551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12020,9 +11599,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12082,9 +11658,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12133,9 +11706,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12184,9 +11754,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12235,9 +11802,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12299,9 +11863,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12363,9 +11924,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12438,9 +11996,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12502,9 +12057,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12592,9 +12144,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12656,9 +12205,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12720,9 +12266,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12784,9 +12327,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12848,9 +12388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12912,9 +12449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12976,9 +12510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13040,9 +12571,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13104,9 +12632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13155,9 +12680,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13206,9 +12728,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13259,9 +12778,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13313,9 +12829,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13367,9 +12880,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13421,9 +12931,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13475,9 +12982,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13529,9 +13033,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13583,9 +13084,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13637,9 +13135,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13690,9 +13185,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13768,9 +13260,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13914,9 +13403,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14062,9 +13548,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14238,9 +13721,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14418,9 +13898,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14499,7 +13976,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "description": "Update an SMS message by its unique ID.\n", "responses": { "200": { "description": "Message", @@ -14519,7 +13996,7 @@ "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -14529,9 +14006,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14643,9 +14117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14698,9 +14169,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14762,9 +14230,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14839,9 +14304,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14916,9 +14378,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14994,9 +14453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15101,9 +14557,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15211,9 +14664,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15298,9 +14748,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15388,9 +14835,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15505,9 +14949,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15625,9 +15066,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15722,9 +15160,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15822,9 +15257,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15929,9 +15361,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16039,9 +15468,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16184,9 +15610,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16331,9 +15754,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16428,9 +15848,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16528,9 +15945,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16625,9 +16039,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16725,9 +16136,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16822,9 +16230,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16922,9 +16327,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17019,9 +16421,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17119,9 +16518,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17174,9 +16570,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17238,9 +16631,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17315,9 +16705,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17392,9 +16779,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17468,9 +16852,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17553,9 +16934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17615,9 +16993,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17694,9 +17069,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17758,9 +17130,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17835,9 +17204,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17923,9 +17289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18013,9 +17376,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18080,9 +17440,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18154,9 +17511,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18230,9 +17584,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18320,9 +17671,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18415,9 +17763,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18493,9 +17838,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18567,9 +17909,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18680,9 +18019,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18815,9 +18151,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18922,9 +18255,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19048,9 +18378,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19108,9 +18435,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19161,9 +18485,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19223,9 +18544,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19313,9 +18631,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19361,9 +18676,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19436,9 +18748,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19496,9 +18805,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19573,9 +18879,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19635,9 +18938,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19709,9 +19009,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19846,9 +19143,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19906,9 +19200,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20023,9 +19314,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20085,9 +19373,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20179,9 +19464,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20260,9 +19542,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20341,9 +19620,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20422,9 +19698,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20503,9 +19776,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20596,9 +19866,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20680,9 +19947,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20761,9 +20025,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20842,9 +20103,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20923,9 +20181,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21004,9 +20259,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21106,9 +20358,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21195,9 +20444,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21255,9 +20501,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21350,9 +20593,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21420,9 +20660,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21516,9 +20753,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21588,9 +20822,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21727,9 +20958,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21787,9 +21015,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21908,9 +21133,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21978,9 +21200,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22075,9 +21294,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22147,9 +21363,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22249,9 +21462,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22330,9 +21540,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22450,9 +21657,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22583,9 +21787,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22664,9 +21865,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22864,11 +22062,11 @@ "description": "", "responses": { "200": { - "description": "Project", + "description": "EmailTemplate", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/project" + "$ref": "#\/components\/schemas\/emailTemplate" } } } @@ -22890,9 +22088,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23156,9 +22351,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23384,9 +22576,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23607,9 +22796,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23849,9 +23035,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24074,9 +23257,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24134,9 +23314,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24251,9 +23428,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24321,9 +23495,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24439,9 +23610,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24511,9 +23679,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24583,9 +23748,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24657,9 +23819,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24743,9 +23902,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24796,9 +23952,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24858,9 +24011,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24920,9 +24070,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24995,9 +24142,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25124,9 +24268,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25185,9 +24326,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25311,9 +24449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25376,9 +24511,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25464,9 +24596,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25564,9 +24693,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25638,9 +24764,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25729,9 +24852,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25798,9 +24918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25867,9 +24984,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26085,9 +25199,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26159,9 +25270,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26233,9 +25341,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26319,9 +25424,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26397,9 +25499,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26484,9 +25583,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26548,9 +25644,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26624,9 +25717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26688,9 +25778,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26765,9 +25852,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26853,9 +25937,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26966,9 +26047,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27040,9 +26118,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27129,9 +26204,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27204,9 +26276,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27303,9 +26372,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27365,9 +26431,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27447,9 +26510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27522,9 +26582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27612,9 +26669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27699,9 +26753,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27786,9 +26837,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27856,9 +26904,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27919,9 +26964,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28006,9 +27048,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28093,9 +27132,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28210,9 +27246,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28315,9 +27348,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28422,9 +27452,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28496,9 +27523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28550,9 +27574,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28613,9 +27634,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28695,9 +27713,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28779,9 +27794,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28864,9 +27876,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28940,9 +27949,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29003,9 +28009,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29058,15 +28061,8 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -29085,9 +28081,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29163,9 +28156,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29226,9 +28216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29287,9 +28274,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29348,9 +28332,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29411,9 +28392,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29493,9 +28471,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29575,9 +28550,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29657,9 +28629,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29718,9 +28687,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29800,9 +28766,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29861,9 +28824,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29915,9 +28875,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29971,9 +28928,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30044,9 +28998,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30127,9 +29078,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30202,9 +29150,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30314,9 +29259,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30386,9 +29328,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30477,9 +29416,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30550,9 +29486,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30634,9 +29567,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30716,9 +29646,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30798,9 +29725,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30869,9 +29793,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30956,9 +29877,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31028,9 +29946,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31100,9 +30015,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31183,9 +30095,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31264,9 +30173,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31355,9 +30261,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31431,9 +30334,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31484,9 +30384,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 94d7f2ed33..d0630d8ac1 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -110,9 +107,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -197,9 +191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -276,9 +267,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -338,9 +326,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -404,9 +389,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -455,9 +437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -524,9 +503,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -597,9 +573,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -666,9 +639,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -747,9 +717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -818,9 +785,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -866,10 +830,10 @@ ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -894,9 +858,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -973,9 +934,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1027,9 +985,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1079,9 +1034,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1131,9 +1083,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1185,9 +1134,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1258,9 +1204,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1336,9 +1279,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1415,9 +1355,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1467,9 +1404,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1543,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1620,9 +1551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1705,9 +1633,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1750,9 +1675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1804,9 +1726,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1855,9 +1774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1931,9 +1847,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2007,9 +1920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2083,9 +1993,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2159,9 +2066,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2223,9 +2127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2280,9 +2181,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2346,9 +2244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2400,9 +2295,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2484,9 +2376,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2563,9 +2452,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2709,9 +2595,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2785,9 +2668,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2856,9 +2736,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2938,9 +2815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2990,9 +2864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3063,9 +2934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3193,9 +3061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3327,9 +3192,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3389,9 +3251,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3881,9 +3740,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3967,9 +3823,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4063,9 +3916,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4164,9 +4014,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4240,9 +4087,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4322,9 +4166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4384,9 +4225,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4463,9 +4301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4527,9 +4362,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4613,9 +4445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4720,9 +4549,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4792,9 +4618,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4894,9 +4717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4968,9 +4788,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5055,9 +4872,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5140,7 +4954,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5164,9 +4978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5278,9 +5089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5363,7 +5171,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5387,9 +5195,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5501,9 +5306,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5586,7 +5388,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -5610,9 +5412,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5724,9 +5523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5818,7 +5614,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -5842,9 +5638,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5965,9 +5758,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6060,7 +5850,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6084,9 +5874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6210,9 +5997,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6305,7 +6089,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6329,9 +6113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6455,9 +6236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6540,7 +6318,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -6564,9 +6342,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6678,9 +6453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6812,9 +6584,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6908,7 +6677,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -6932,9 +6701,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7051,9 +6817,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7136,7 +6899,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7160,9 +6923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7305,9 +7065,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7379,9 +7136,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7438,7 +7192,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7462,9 +7216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7575,9 +7326,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7664,9 +7412,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7775,9 +7520,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7874,9 +7616,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7977,9 +7716,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8063,9 +7799,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8148,9 +7881,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8271,9 +8001,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8345,9 +8072,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8428,9 +8152,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8504,9 +8225,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8754,9 +8472,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8807,9 +8522,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8859,9 +8571,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8921,9 +8630,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9148,9 +8854,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9212,9 +8915,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9298,9 +8998,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9397,9 +9094,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9469,9 +9163,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9534,9 +9225,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9601,9 +9289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9689,9 +9374,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9757,9 +9439,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9834,9 +9513,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -9924,9 +9600,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10043,9 +9716,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10110,9 +9780,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10184,9 +9851,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10246,9 +9910,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10335,9 +9996,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10407,9 +10065,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10496,9 +10151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10572,9 +10224,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10628,9 +10277,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10682,9 +10328,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10734,9 +10377,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10786,9 +10426,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10838,9 +10475,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10901,9 +10535,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10953,9 +10584,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11005,9 +10633,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11057,9 +10682,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11122,9 +10744,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11187,9 +10806,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11263,9 +10879,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11328,9 +10941,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11419,9 +11029,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11484,9 +11091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11549,9 +11153,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11614,9 +11215,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11679,9 +11277,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11744,9 +11339,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11809,9 +11401,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11874,9 +11463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11939,9 +11525,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11991,9 +11574,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12043,9 +11623,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12097,9 +11674,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12153,9 +11727,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12209,9 +11780,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12265,9 +11833,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12321,9 +11886,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12377,9 +11939,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12433,9 +11992,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12489,9 +12045,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12544,9 +12097,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12623,9 +12173,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12770,9 +12317,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12919,9 +12463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13096,9 +12637,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13277,9 +12815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13359,7 +12894,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "description": "Update an SMS message by its unique ID.\n", "responses": { "200": { "description": "Message", @@ -13379,7 +12914,7 @@ "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -13389,9 +12924,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13504,9 +13036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13560,9 +13089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13625,9 +13151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13703,9 +13226,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13781,9 +13301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13860,9 +13377,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13968,9 +13482,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14079,9 +13590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14167,9 +13675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14258,9 +13763,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14376,9 +13878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14497,9 +13996,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14595,9 +14091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14696,9 +14189,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14804,9 +14294,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14915,9 +14402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15061,9 +14545,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15209,9 +14690,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15307,9 +14785,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15408,9 +14883,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15506,9 +14978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15607,9 +15076,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15705,9 +15171,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15806,9 +15269,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15904,9 +15364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16005,9 +15462,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16061,9 +15515,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16126,9 +15577,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16204,9 +15652,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16282,9 +15727,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16359,9 +15801,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16445,9 +15884,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16508,9 +15944,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16588,9 +16021,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16653,9 +16083,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16731,9 +16158,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16820,9 +16244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -16912,9 +16333,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16980,9 +16398,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17056,9 +16471,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17132,9 +16544,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17262,9 +16671,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17324,9 +16730,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17451,9 +16854,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17517,9 +16917,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17607,9 +17004,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17709,9 +17103,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17785,9 +17176,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17878,9 +17266,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17949,9 +17334,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18020,9 +17402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18240,9 +17619,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18318,9 +17694,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18398,9 +17771,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18487,9 +17857,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18553,9 +17920,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18631,9 +17995,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18699,9 +18060,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18789,9 +18147,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18904,9 +18259,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18980,9 +18332,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19071,9 +18420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19148,9 +18494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19249,9 +18592,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19313,9 +18653,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19397,9 +18734,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19473,9 +18807,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19564,9 +18895,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19652,9 +18980,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19740,9 +19065,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19811,9 +19133,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19875,9 +19194,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19963,9 +19279,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20051,9 +19364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20169,9 +19479,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20275,9 +19582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20383,9 +19687,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20438,9 +19739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20502,9 +19800,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20585,9 +19880,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20670,9 +19962,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20756,9 +20045,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20833,9 +20119,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20897,9 +20180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20953,15 +20233,8 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -20980,9 +20253,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21059,9 +20329,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21123,9 +20390,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21185,9 +20449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21247,9 +20508,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21311,9 +20569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21394,9 +20649,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21477,9 +20729,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21560,9 +20809,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21622,9 +20868,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21705,9 +20948,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21767,9 +21007,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21822,9 +21059,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21879,9 +21113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21953,9 +21184,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22037,9 +21265,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22113,9 +21338,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22226,9 +21448,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22299,9 +21518,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22391,9 +21607,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22465,9 +21678,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22550,9 +21760,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22633,9 +21840,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 77025ec042..17eef07fdc 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -102,9 +102,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -155,9 +152,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -248,9 +242,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -330,9 +321,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -394,9 +382,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -459,9 +444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -512,9 +494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -581,9 +560,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -656,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -724,9 +697,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -805,9 +775,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -875,9 +842,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -922,14 +886,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "account" ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -949,9 +918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1031,9 +997,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1086,9 +1049,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1139,9 +1099,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1192,9 +1149,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1247,9 +1201,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1322,9 +1273,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1403,9 +1351,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1485,9 +1430,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1538,9 +1480,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1616,9 +1555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1696,9 +1632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1785,9 +1718,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1833,9 +1763,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1888,9 +1815,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1941,9 +1865,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2021,9 +1942,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2098,9 +2016,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2236,9 +2151,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2316,9 +2228,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2396,9 +2305,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2459,9 +2365,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2517,9 +2420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2582,9 +2482,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2636,9 +2533,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2770,9 +2661,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], @@ -2798,9 +2687,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2862,9 +2748,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2951,9 +2834,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3040,9 +2920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3181,9 +3058,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3261,9 +3135,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3334,9 +3205,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3419,9 +3287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3472,9 +3337,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3555,9 +3417,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3684,9 +3543,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3817,9 +3673,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3884,9 +3737,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4375,9 +4225,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4462,9 +4309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4557,9 +4401,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4652,9 +4493,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4736,9 +4574,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4844,9 +4679,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4936,9 +4768,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5035,9 +4864,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5117,9 +4943,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5202,9 +5025,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5323,9 +5143,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5397,9 +5214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5473,9 +5287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5549,9 +5360,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5605,9 +5413,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5661,9 +5466,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5717,9 +5519,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5773,9 +5572,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5829,9 +5625,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5885,9 +5678,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5941,9 +5731,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5998,9 +5785,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6056,9 +5840,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -6087,9 +5869,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6161,9 +5940,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6246,9 +6022,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6340,9 +6113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6412,9 +6182,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6503,9 +6270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6577,9 +6341,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6651,9 +6412,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6852,9 +6610,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6926,9 +6681,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7003,9 +6755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7097,9 +6846,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7161,9 +6907,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7238,9 +6981,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7304,9 +7044,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7389,9 +7126,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7506,9 +7240,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7578,9 +7309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7666,9 +7394,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7739,9 +7464,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7837,9 +7559,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7900,9 +7619,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index efdcca1579..b2f4797690 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -114,9 +114,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -166,9 +163,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -251,9 +245,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -304,9 +295,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -385,9 +373,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -448,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -512,9 +494,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -565,9 +544,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -633,9 +609,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -707,9 +680,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -774,9 +744,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -854,9 +821,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -923,9 +887,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -970,14 +931,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "account" ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -997,9 +963,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1078,9 +1041,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1132,9 +1092,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1184,9 +1141,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1236,9 +1190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1290,9 +1241,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1364,9 +1312,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1444,9 +1389,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1525,9 +1467,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1577,9 +1516,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1654,9 +1590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1733,9 +1666,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1821,9 +1751,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1868,9 +1795,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1922,9 +1846,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1975,9 +1896,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2055,9 +1973,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2132,9 +2047,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2270,9 +2182,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2350,9 +2259,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2430,9 +2336,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2492,9 +2395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2549,9 +2449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2613,9 +2510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2666,9 +2560,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2751,9 +2642,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2798,9 +2686,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], @@ -2826,9 +2712,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2889,9 +2772,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2978,9 +2858,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3067,9 +2944,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3208,9 +3082,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3288,9 +3159,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3360,9 +3228,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3444,9 +3309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3496,9 +3358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3578,9 +3437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3707,9 +3563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3840,9 +3693,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3907,9 +3757,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4398,9 +4245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4485,9 +4329,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4580,9 +4421,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4673,9 +4511,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4745,9 +4580,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4797,9 +4629,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4871,9 +4700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4957,9 +4783,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5031,9 +4854,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5092,9 +4912,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5172,9 +4989,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5235,9 +5049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5317,9 +5128,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5426,9 +5234,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5495,9 +5300,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5598,9 +5400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5669,9 +5468,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5752,9 +5548,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5829,7 +5622,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5858,9 +5653,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5968,9 +5760,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6045,7 +5834,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6074,9 +5865,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6184,9 +5972,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6261,7 +6046,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6290,9 +6077,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6400,9 +6184,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6487,7 +6268,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6516,9 +6299,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6636,9 +6416,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6725,7 +6502,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6754,9 +6533,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6878,9 +6654,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6967,7 +6740,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6996,9 +6771,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7120,9 +6892,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7197,7 +6966,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7226,9 +6997,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7336,9 +7104,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7471,9 +7236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7561,7 +7323,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7590,9 +7354,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7706,9 +7467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7783,7 +7541,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7812,9 +7572,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7953,9 +7710,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8024,9 +7778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8071,7 +7822,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -8100,9 +7853,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8208,9 +7958,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8292,9 +8039,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8400,9 +8144,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8492,9 +8233,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8591,9 +8329,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8671,9 +8406,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8761,9 +8493,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8842,9 +8571,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8964,9 +8690,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9035,9 +8758,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9113,9 +8833,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9195,9 +8912,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9285,9 +8999,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9359,9 +9070,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9441,9 +9149,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9515,9 +9220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9788,9 +9490,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9842,9 +9541,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9895,9 +9591,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9993,9 +9686,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10055,9 +9745,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10129,9 +9816,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10190,9 +9874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10433,9 +10114,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10496,9 +10174,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10578,9 +10253,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10672,9 +10344,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10741,9 +10410,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10805,9 +10471,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10845,7 +10508,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "functions" ], @@ -10871,9 +10536,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10955,9 +10617,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11027,9 +10686,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11101,9 +10757,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11186,9 +10839,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11307,9 +10957,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11372,9 +11019,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11443,9 +11087,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11525,9 +11166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11586,9 +11224,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11674,9 +11309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11743,9 +11375,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11831,9 +11460,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11904,9 +11530,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11980,9 +11603,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12054,9 +11674,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12107,9 +11724,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12160,9 +11774,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12213,9 +11824,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12275,9 +11883,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12328,9 +11933,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12381,9 +11983,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12434,9 +12033,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12498,9 +12094,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12562,9 +12155,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12635,9 +12225,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12699,9 +12286,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12787,9 +12371,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12851,9 +12432,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12915,9 +12493,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12979,9 +12554,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13043,9 +12615,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13107,9 +12676,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13171,9 +12737,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13235,9 +12798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13299,9 +12859,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13352,9 +12909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13405,9 +12959,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13460,9 +13011,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13516,9 +13064,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13572,9 +13117,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13628,9 +13170,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13684,9 +13223,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13740,9 +13276,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13796,9 +13329,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13852,9 +13382,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13907,9 +13434,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13984,9 +13508,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14144,9 +13665,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14301,9 +13819,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14498,9 +14013,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14694,9 +14206,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14788,7 +14297,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "description": "Update an SMS message by its unique ID.\n", "responses": { "200": { "description": "Message", @@ -14804,7 +14313,7 @@ "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -14814,9 +14323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14932,9 +14438,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14962,9 +14465,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -14991,9 +14492,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15055,9 +14553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15131,9 +14626,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15207,9 +14699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15284,9 +14773,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15401,9 +14887,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15516,9 +14999,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15609,9 +15089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15700,9 +15177,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15829,9 +15303,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15956,9 +15427,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16061,9 +15529,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16164,9 +15629,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16281,9 +15743,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16396,9 +15855,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16557,9 +16013,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16715,9 +16168,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16820,9 +16270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16923,9 +16370,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17028,9 +16472,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17131,9 +16572,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17236,9 +16674,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17339,9 +16774,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17444,9 +16876,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17547,9 +16976,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17577,9 +17003,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17606,9 +17030,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17670,9 +17091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17746,9 +17164,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17822,9 +17237,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17897,9 +17309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17989,9 +17398,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18051,9 +17457,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18105,9 +17508,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18134,9 +17535,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18198,9 +17596,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18274,9 +17669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18359,9 +17751,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18449,9 +17838,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18487,9 +17873,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18518,9 +17902,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18590,9 +17971,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18665,9 +18043,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18761,9 +18136,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18851,9 +18223,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18933,9 +18302,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19006,9 +18372,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19129,9 +18492,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19251,9 +18611,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19367,9 +18724,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19482,9 +18836,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19542,9 +18893,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19597,9 +18945,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19659,9 +19004,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19745,9 +19087,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19795,9 +19134,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19874,9 +19210,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19934,9 +19267,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20013,9 +19343,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20075,9 +19402,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20148,9 +19472,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20300,9 +19621,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20360,9 +19678,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20487,9 +19802,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20549,9 +19861,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20643,9 +19952,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20723,9 +20029,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20803,9 +20106,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20883,9 +20183,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20963,9 +20260,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21057,9 +20351,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21140,9 +20431,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21220,9 +20508,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21300,9 +20585,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21380,9 +20662,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21460,9 +20739,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21559,9 +20835,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21648,9 +20921,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21708,9 +20978,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21804,9 +21071,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21872,9 +21136,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21969,9 +21230,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22039,9 +21297,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22180,9 +21435,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22240,9 +21492,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22364,9 +21613,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22432,9 +21678,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22531,9 +21774,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22601,9 +21841,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22703,9 +21940,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22783,9 +22017,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22886,7 +22117,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "projects" ], @@ -22912,9 +22145,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23052,9 +22282,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23132,9 +22359,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23332,9 +22556,9 @@ "description": "", "responses": { "200": { - "description": "Project", + "description": "EmailTemplate", "schema": { - "$ref": "#\/definitions\/project" + "$ref": "#\/definitions\/emailTemplate" } } }, @@ -23354,9 +22578,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23619,9 +22840,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23843,9 +23061,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24062,9 +23277,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24299,9 +23511,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24520,9 +23729,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24580,9 +23786,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24702,9 +23905,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24770,9 +23970,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24893,9 +24090,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24963,9 +24157,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25033,9 +24224,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25106,9 +24294,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25197,9 +24382,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25252,9 +24434,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25314,9 +24493,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25376,9 +24552,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25450,9 +24623,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25591,9 +24761,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25652,9 +24819,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25787,9 +24951,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25852,9 +25013,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25937,9 +25095,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26031,9 +25186,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26103,9 +25255,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26194,9 +25343,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26268,9 +25414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26342,9 +25485,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26543,9 +25683,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26615,9 +25752,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26689,9 +25823,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26773,9 +25904,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26850,9 +25978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26944,9 +26069,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27008,9 +26130,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27085,9 +26204,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27149,9 +26265,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27225,9 +26338,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27310,9 +26420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27427,9 +26534,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27499,9 +26603,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27587,9 +26688,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27660,9 +26758,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27757,9 +26852,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27819,9 +26911,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27900,9 +26989,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27974,9 +27060,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28071,9 +27154,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28164,9 +27244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28257,9 +27334,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28328,9 +27402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28391,9 +27462,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28484,9 +27552,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28577,9 +27642,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28705,9 +27767,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28819,9 +27878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28933,9 +27989,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29007,9 +28060,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29063,9 +28113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29126,9 +28173,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29207,9 +28251,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29291,9 +28332,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29375,9 +28413,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29450,9 +28485,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29513,9 +28545,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29563,19 +28592,14 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -29594,9 +28618,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29670,9 +28691,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29733,9 +28751,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29794,9 +28809,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29855,9 +28867,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29918,9 +28927,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29999,9 +29005,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30080,9 +29083,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30161,9 +29161,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30222,9 +29219,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30303,9 +29297,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30364,9 +29355,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30420,9 +29408,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30478,9 +29463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30549,9 +29531,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30631,9 +29610,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30705,9 +29681,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30820,9 +29793,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30890,9 +29860,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30955,9 +29922,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -30984,9 +29949,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31055,9 +30017,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31139,9 +30098,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31220,9 +30176,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31301,9 +30254,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31370,9 +30320,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31457,9 +30404,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31527,9 +30471,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31597,9 +30538,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31676,9 +30614,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31730,7 +30665,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "vcs" ], @@ -31756,9 +30693,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31844,9 +30778,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31919,9 +30850,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31974,9 +30902,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 5b4fbe92b7..3d787172a9 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -117,9 +117,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -171,9 +168,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -264,9 +258,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -347,9 +338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -412,9 +400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -478,9 +463,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -531,9 +513,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -601,9 +580,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -677,9 +653,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -746,9 +719,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -828,9 +798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -899,9 +866,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -946,14 +910,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "account" ], "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", "responses": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -973,9 +942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1056,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1112,9 +1075,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1166,9 +1126,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1220,9 +1177,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1276,9 +1230,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1352,9 +1303,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1434,9 +1382,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1517,9 +1462,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1571,9 +1513,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1650,9 +1589,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1731,9 +1667,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1821,9 +1754,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1870,9 +1800,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1926,9 +1853,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1979,9 +1903,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2059,9 +1980,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2139,9 +2057,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2219,9 +2134,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2299,9 +2211,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2363,9 +2272,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2422,9 +2328,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2488,9 +2391,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2544,9 +2444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2633,9 +2530,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2863,9 +2754,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2943,9 +2831,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3017,9 +2902,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3103,9 +2985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3157,9 +3036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3241,9 +3117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3372,9 +3245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3507,9 +3377,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3576,9 +3443,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4069,9 +3933,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4158,9 +4019,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4255,9 +4113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4350,9 +4205,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4425,9 +4277,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4512,9 +4361,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4574,9 +4420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4655,9 +4498,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4719,9 +4559,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4802,9 +4639,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4912,9 +4746,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4982,9 +4813,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5086,9 +4914,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5158,9 +4983,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5242,9 +5064,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5320,7 +5139,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5349,9 +5170,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5460,9 +5278,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5538,7 +5353,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5567,9 +5384,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5678,9 +5492,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5756,7 +5567,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5785,9 +5598,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5896,9 +5706,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5984,7 +5791,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6013,9 +5822,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6134,9 +5940,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6224,7 +6027,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6253,9 +6058,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6378,9 +6180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6468,7 +6267,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6497,9 +6298,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6622,9 +6420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6700,7 +6495,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6729,9 +6526,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6840,9 +6634,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6976,9 +6767,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7067,7 +6855,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7096,9 +6886,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7213,9 +7000,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7291,7 +7075,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7320,9 +7106,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7462,9 +7245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7534,9 +7314,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7582,7 +7359,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7611,9 +7390,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7720,9 +7496,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7806,9 +7579,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7916,9 +7686,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8010,9 +7777,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8111,9 +7875,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8193,9 +7954,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8275,9 +8033,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8398,9 +8153,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8470,9 +8222,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8549,9 +8298,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8624,9 +8370,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8898,9 +8641,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8953,9 +8693,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9007,9 +8744,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9069,9 +8803,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9313,9 +9044,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9377,9 +9105,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9460,9 +9185,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9555,9 +9277,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9625,9 +9344,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9690,9 +9406,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9731,7 +9444,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "functions" ], @@ -9757,9 +9472,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9842,9 +9554,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9915,9 +9624,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9990,9 +9696,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10077,9 +9780,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10200,9 +9900,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10267,9 +9964,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10339,9 +10033,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10401,9 +10092,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10490,9 +10178,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10560,9 +10245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10649,9 +10331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10723,9 +10402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10801,9 +10477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10877,9 +10550,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10931,9 +10601,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10985,9 +10652,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11039,9 +10703,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11102,9 +10763,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11156,9 +10814,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11210,9 +10865,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11264,9 +10916,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11329,9 +10978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11394,9 +11040,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11468,9 +11111,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11533,9 +11173,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11622,9 +11259,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11687,9 +11321,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11752,9 +11383,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11817,9 +11445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11882,9 +11507,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11947,9 +11569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12012,9 +11631,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12077,9 +11693,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12142,9 +11755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12196,9 +11806,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12250,9 +11857,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12306,9 +11910,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12364,9 +11965,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12422,9 +12020,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12480,9 +12075,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12538,9 +12130,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12596,9 +12185,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12654,9 +12240,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12712,9 +12295,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12769,9 +12349,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12847,9 +12424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13008,9 +12582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13166,9 +12737,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13364,9 +12932,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13561,9 +13126,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13656,7 +13218,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "description": "Update an SMS message by its unique ID.\n", "responses": { "200": { "description": "Message", @@ -13672,7 +13234,7 @@ "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -13682,9 +13244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13801,9 +13360,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13832,9 +13388,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -13861,9 +13415,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13926,9 +13477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14003,9 +13551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14080,9 +13625,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14158,9 +13700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14276,9 +13815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14392,9 +13928,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14486,9 +14019,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14578,9 +14108,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14708,9 +14235,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14836,9 +14360,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14942,9 +14463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15046,9 +14564,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15164,9 +14679,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15280,9 +14792,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15442,9 +14951,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15601,9 +15107,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15707,9 +15210,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15811,9 +15311,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15917,9 +15414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16021,9 +15515,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16127,9 +15618,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16231,9 +15719,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16337,9 +15822,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16441,9 +15923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16472,9 +15951,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -16501,9 +15978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16566,9 +16040,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16643,9 +16114,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16720,9 +16188,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16796,9 +16261,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16889,9 +16351,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16952,9 +16411,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17007,9 +16463,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17036,9 +16490,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17101,9 +16552,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17178,9 +16626,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17264,9 +16709,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17356,9 +16798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17395,9 +16834,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17426,9 +16863,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17500,9 +16934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17575,9 +17006,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17717,9 +17145,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17779,9 +17204,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17915,9 +17337,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17981,9 +17400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18068,9 +17484,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18164,9 +17577,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18238,9 +17648,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18331,9 +17738,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18407,9 +17811,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18483,9 +17884,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18686,9 +18084,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18762,9 +18157,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18841,9 +18233,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18937,9 +18326,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19003,9 +18389,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19082,9 +18465,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19150,9 +18530,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19237,9 +18614,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19356,9 +18730,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19430,9 +18801,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19520,9 +18888,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19595,9 +18960,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19694,9 +19056,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19758,9 +19117,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19841,9 +19197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19916,9 +19269,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20014,9 +19364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20108,9 +19455,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20202,9 +19546,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20274,9 +19615,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20338,9 +19676,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20432,9 +19767,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20526,9 +19858,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20655,9 +19984,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20770,9 +20096,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20885,9 +20208,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20942,9 +20262,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21006,9 +20323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21088,9 +20402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21173,9 +20484,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21258,9 +20566,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21334,9 +20639,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21398,9 +20700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21449,19 +20748,14 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -21480,9 +20774,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21557,9 +20848,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21621,9 +20909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21683,9 +20968,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21745,9 +21027,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21809,9 +21088,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21891,9 +21167,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21973,9 +21246,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22055,9 +21325,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22117,9 +21384,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22199,9 +21463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22261,9 +21522,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22318,9 +21576,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22377,9 +21632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22449,9 +21701,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22532,9 +21781,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22607,9 +21853,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22723,9 +21966,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22794,9 +22034,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22860,9 +22097,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -22889,9 +22124,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22961,9 +22193,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -23046,9 +22275,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -23128,9 +22354,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 6935029450..727ed746a4 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -22,6 +22,11 @@ use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; use Appwrite\Utopia\Database\Validator\CustomId; @@ -282,13 +287,19 @@ App::post('/v1/account') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/account/create.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'account', + name: 'create', + description: '/docs/references/account/create.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') @@ -419,15 +430,19 @@ App::get('/v1/account') ->desc('Get account') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/account/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'get', + description: '/docs/references/account/get.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -444,12 +459,19 @@ App::delete('/v1/account') ->label('scope', 'account') ->label('audits.event', 'user.delete') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/account/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'delete', + description: '/docs/references/account/delete.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->inject('user') ->inject('project') ->inject('response') @@ -489,14 +511,19 @@ App::get('/v1/account/sessions') ->desc('List sessions') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listSessions') - ->label('sdk.description', '/docs/references/account/list-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION_LIST) - ->label('sdk.offline.model', '/account/sessions') + ->label('sdk', new Method( + namespace: 'account', + name: 'listSessions', + description: '/docs/references/account/list-sessions.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->inject('response') ->inject('user') ->inject('locale') @@ -533,12 +560,19 @@ App::delete('/v1/account/sessions') ->label('event', 'users.[userId].sessions.[sessionId].delete') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteSessions') - ->label('sdk.description', '/docs/references/account/delete-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteSessions', + description: '/docs/references/account/delete-sessions.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->label('abuse-limit', 100) ->inject('request') ->inject('response') @@ -595,15 +629,19 @@ App::get('/v1/account/sessions/:sessionId') ->desc('Get session') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getSession') - ->label('sdk.description', '/docs/references/account/get-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) - ->label('sdk.offline.model', '/account/sessions') - ->label('sdk.offline.key', '{sessionId}') + ->label('sdk', new Method( + namespace: 'account', + name: 'getSession', + description: '/docs/references/account/get-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to get the current device session.') ->inject('response') ->inject('user') @@ -644,12 +682,19 @@ App::delete('/v1/account/sessions/:sessionId') ->label('event', 'users.[userId].sessions.[sessionId].delete') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteSession') - ->label('sdk.description', '/docs/references/account/delete-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteSession', + description: '/docs/references/account/delete-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->label('abuse-limit', 100) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to delete the current device session.') ->inject('requestTimestamp') @@ -725,13 +770,19 @@ App::patch('/v1/account/sessions/:sessionId') ->label('audits.event', 'session.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateSession') - ->label('sdk.description', '/docs/references/account/update-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateSession', + description: '/docs/references/account/update-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to update the current device session.') ->inject('response') @@ -803,13 +854,19 @@ App::post('/v1/account/sessions/email') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createEmailPasswordSession') - ->label('sdk.description', '/docs/references/account/create-session-email-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createEmailPasswordSession', + description: '/docs/references/account/create-session-email-password.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},email:{param-email}') ->param('email', '', new Email(), 'User email.') @@ -937,13 +994,19 @@ App::post('/v1/account/sessions/anonymous') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createAnonymousSession') - ->label('sdk.description', '/docs/references/account/create-session-anonymous.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createAnonymousSession', + description: '/docs/references/account/create-session-anonymous.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->inject('request') @@ -1074,13 +1137,19 @@ App::post('/v1/account/sessions/token') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -1101,14 +1170,21 @@ App::get('/v1/account/sessions/oauth2/:provider') ->groups(['api', 'account']) ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'sessions.write') - ->label('sdk.auth', []) - ->label('sdk.hide', [APP_PLATFORM_SERVER]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createOAuth2Session') - ->label('sdk.description', '/docs/references/account/create-session-oauth2.md') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') + ->label('sdk', new Method( + namespace: 'account', + name: 'createOAuth2Session', + description: '/docs/references/account/create-session-oauth2.md', + type: MethodType::WEBAUTH, + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + hide: [APP_PLATFORM_SERVER], + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') @@ -1691,13 +1767,20 @@ App::get('/v1/account/tokens/oauth2/:provider') ->groups(['api', 'account']) ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'sessions.write') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createOAuth2Token') - ->label('sdk.description', '/docs/references/account/create-token-oauth2.md') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') + ->label('sdk', new Method( + namespace: 'account', + name: 'createOAuth2Token', + description: '/docs/references/account/create-token-oauth2.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + type: MethodType::WEBAUTH, + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') @@ -1764,13 +1847,19 @@ App::post('/v1/account/tokens/magic-url') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMagicURLToken') - ->label('sdk.description', '/docs/references/account/create-token-magic-url.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createMagicURLToken', + description: '/docs/references/account/create-token-magic-url.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 60) ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -2007,13 +2096,19 @@ App::post('/v1/account/tokens/email') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createEmailToken') - ->label('sdk.description', '/docs/references/account/create-token-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createEmailToken', + description: '/docs/references/account/create-token-email.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -2236,14 +2331,20 @@ App::put('/v1/account/sessions/magic-url') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.deprecated', true) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMagicURLSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMagicURLSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON, + deprecated: true, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -2267,14 +2368,20 @@ App::put('/v1/account/sessions/phone') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.deprecated', true) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhoneSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhoneSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON, + deprecated: true, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -2299,13 +2406,19 @@ App::post('/v1/account/tokens/phone') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPhoneToken') - ->label('sdk.description', '/docs/references/account/create-token-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPhoneToken', + description: '/docs/references/account/create-token-phone.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},phone:{param-phone}', 'url:{url},ip:{ip}']) ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') @@ -2501,13 +2614,19 @@ App::post('/v1/account/jwts') ->groups(['api', 'account', 'auth']) ->label('scope', 'account') ->label('auth.type', 'jwt') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createJWT') - ->label('sdk.description', '/docs/references/account/create-jwt.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'account', + name: 'createJWT', + description: '/docs/references/account/create-jwt.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 100) ->label('abuse-key', 'url:{url},userId:{userId}') ->inject('response') @@ -2543,15 +2662,19 @@ App::get('/v1/account/prefs') ->desc('Get account preferences') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/account/get-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/account/prefs') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'getPrefs', + description: '/docs/references/account/get-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -2565,13 +2688,19 @@ App::get('/v1/account/logs') ->desc('List logs') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/account/list-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'account', + name: 'listLogs', + description: '/docs/references/account/list-logs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') ->inject('user') @@ -2633,15 +2762,19 @@ App::patch('/v1/account/name') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/account/update-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateName', + description: '/docs/references/account/update-name.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('name', '', new Text(128), 'User name. Max length: 128 chars.') ->inject('requestTimestamp') ->inject('response') @@ -2667,15 +2800,19 @@ App::patch('/v1/account/password') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePassword') - ->label('sdk.description', '/docs/references/account/update-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePassword', + description: '/docs/references/account/update-password.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary']) ->param('oldPassword', '', new Password(), 'Current user password. Must be at least 8 chars.', true) @@ -2736,15 +2873,19 @@ App::patch('/v1/account/email') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/account/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateEmail', + description: '/docs/references/account/update-email.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password. Must be at least 8 chars.') ->inject('requestTimestamp') @@ -2828,15 +2969,19 @@ App::patch('/v1/account/phone') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhone') - ->label('sdk.description', '/docs/references/account/update-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhone', + description: '/docs/references/account/update-phone.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.') ->param('password', '', new Password(), 'User password. Must be at least 8 chars.') ->inject('requestTimestamp') @@ -2909,15 +3054,19 @@ App::patch('/v1/account/prefs') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/account/update-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account/prefs') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePrefs', + description: '/docs/references/account/update-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.') ->inject('requestTimestamp') ->inject('response') @@ -2942,13 +3091,19 @@ App::patch('/v1/account/status') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateStatus') - ->label('sdk.description', '/docs/references/account/update-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateStatus', + description: '/docs/references/account/update-status.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON, + )) ->inject('requestTimestamp') ->inject('request') ->inject('response') @@ -2986,13 +3141,19 @@ App::post('/v1/account/recovery') ->label('audits.event', 'recovery.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createRecovery') - ->label('sdk.description', '/docs/references/account/create-recovery.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createRecovery', + description: '/docs/references/account/create-recovery.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('email', '', new Email(), 'User email.') @@ -3166,13 +3327,19 @@ App::put('/v1/account/recovery') ->label('audits.event', 'recovery.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateRecovery') - ->label('sdk.description', '/docs/references/account/update-recovery.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateRecovery', + description: '/docs/references/account/update-recovery.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3250,13 +3417,19 @@ App::post('/v1/account/verification') ->label('event', 'users.[userId].verification.[tokenId].create') ->label('audits.event', 'verification.create') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createVerification') - ->label('sdk.description', '/docs/references/account/create-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createVerification', + description: '/docs/references/account/create-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page @@ -3415,13 +3588,19 @@ App::put('/v1/account/verification') ->label('event', 'users.[userId].verification.[tokenId].update') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateVerification') - ->label('sdk.description', '/docs/references/account/update-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateVerification', + description: '/docs/references/account/update-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3475,13 +3654,19 @@ App::post('/v1/account/verification/phone') ->label('event', 'users.[userId].verification.[tokenId].create') ->label('audits.event', 'verification.create') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPhoneVerification') - ->label('sdk.description', '/docs/references/account/create-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPhoneVerification', + description: '/docs/references/account/create-phone-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},userId:{userId}', 'url:{url},ip:{ip}']) ->inject('request') @@ -3626,13 +3811,19 @@ App::put('/v1/account/verification/phone') ->label('event', 'users.[userId].verification.[tokenId].update') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhoneVerification') - ->label('sdk.description', '/docs/references/account/update-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhoneVerification', + description: '/docs/references/account/update-phone-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3685,15 +3876,19 @@ App::patch('/v1/account/mfa') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMFA') - ->label('sdk.description', '/docs/references/account/update-mfa.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMFA', + description: '/docs/references/account/update-mfa.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('mfa', null, new Boolean(), 'Enable or disable MFA.') ->inject('requestTimestamp') ->inject('response') @@ -3734,15 +3929,19 @@ App::get('/v1/account/mfa/factors') ->desc('List factors') ->groups(['api', 'account', 'mfa']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listMfaFactors') - ->label('sdk.description', '/docs/references/account/list-mfa-factors.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_FACTORS) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'listMfaFactors', + description: '/docs/references/account/list-mfa-factors.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_FACTORS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -3770,15 +3969,19 @@ App::post('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/create-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_TYPE) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaAuthenticator', + description: '/docs/references/account/create-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_TYPE, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator. Must be `' . Type::TOTP . '`') ->inject('requestTimestamp') ->inject('response') @@ -3842,15 +4045,19 @@ App::put('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/update-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaAuthenticator', + description: '/docs/references/account/update-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->param('otp', '', new Text(256), 'Valid verification token.') ->inject('response') @@ -3907,15 +4114,19 @@ App::post('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/create-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaRecoveryCodes', + description: '/docs/references/account/create-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->inject('dbForProject') @@ -3949,15 +4160,19 @@ App::patch('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/update-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaRecoveryCodes', + description: '/docs/references/account/update-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('dbForProject') ->inject('response') ->inject('user') @@ -3986,15 +4201,19 @@ App::get('/v1/account/mfa/recovery-codes') ->desc('Get MFA recovery codes') ->groups(['api', 'account', 'mfaProtected']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/get-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'getMfaRecoveryCodes', + description: '/docs/references/account/get-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -4020,12 +4239,19 @@ App::delete('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/delete-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteMfaAuthenticator', + description: '/docs/references/account/delete-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->inject('response') ->inject('user') @@ -4058,13 +4284,19 @@ App::post('/v1/account/mfa/challenge') ->label('audits.event', 'challenge.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaChallenge') - ->label('sdk.description', '/docs/references/account/create-mfa-challenge.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_CHALLENGE) + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaChallenge', + description: '/docs/references/account/create-mfa-challenge.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_CHALLENGE, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('factor', '', new WhiteList([Type::EMAIL, Type::PHONE, Type::TOTP, Type::RECOVERY_CODE]), 'Factor used for verification. Must be one of following: `' . Type::EMAIL . '`, `' . Type::PHONE . '`, `' . Type::TOTP . '`, `' . Type::RECOVERY_CODE . '`.') @@ -4271,12 +4503,19 @@ App::put('/v1/account/mfa/challenge') ->label('audits.event', 'challenges.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaChallenge') - ->label('sdk.description', '/docs/references/account/update-mfa-challenge.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaChallenge', + description: '/docs/references/account/update-mfa-challenge.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},challengeId:{param-challengeId}') ->param('challengeId', '', new Text(256), 'ID of the challenge.') @@ -4357,12 +4596,19 @@ App::post('/v1/account/targets/push') ->label('audits.event', 'target.create') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].create') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPushTarget', + description: '', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TARGET, + ) + ], + contentType: ContentType::JSON + )) ->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true) @@ -4430,12 +4676,19 @@ App::put('/v1/account/targets/:targetId/push') ->label('audits.event', 'target.update') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].update') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePushTarget', + description: '', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ], + contentType: ContentType::JSON + )) ->param('targetId', '', new UID(), 'Target ID.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->inject('queueForEvents') @@ -4487,12 +4740,19 @@ App::delete('/v1/account/targets/:targetId/push') ->label('audits.event', 'target.delete') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deletePushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'deletePushTarget', + description: '', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('targetId', '', new UID(), 'Target ID.') ->inject('queueForEvents') ->inject('queueForDeletes') @@ -4530,14 +4790,19 @@ App::get('/v1/account/identities') ->desc('List identities') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listIdentities') - ->label('sdk.description', '/docs/references/account/list-identities.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) - ->label('sdk.offline.model', '/account/identities') + ->label('sdk', new Method( + namespace: 'account', + name: 'listIdentities', + description: '/docs/references/account/list-identities.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_IDENTITY_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('queries', [], new Identities(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Identities::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('user') @@ -4596,12 +4861,19 @@ App::delete('/v1/account/identities/:identityId') ->label('audits.event', 'identity.delete') ->label('audits.resource', 'identity/{request.$identityId}') ->label('audits.userId', '{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteIdentity') - ->label('sdk.description', '/docs/references/account/delete-identity.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteIdentity', + description: '/docs/references/account/delete-identity.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('identityId', '', new UID(), 'Identity ID.') ->inject('response') ->inject('dbForProject') @@ -4622,4 +4894,4 @@ App::delete('/v1/account/identities/:identityId') ->setPayload($response->output($identity, Response::MODEL_IDENTITY)); return $response->noContent(); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index f73f8a148a..2b0f7d9e06 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1,6 +1,11 @@ <?php use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\URL\URL as URLParse; use Appwrite\Utopia\Response; use chillerlan\QRCode\QRCode; @@ -164,13 +169,20 @@ App::get('/v1/avatars/credit-cards/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/credit-card') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getCreditCard') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-credit-card.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getCreditCard', + description: '/docs/references/avatars/get-credit-card.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -184,13 +196,20 @@ App::get('/v1/avatars/browsers/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/browser') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getBrowser') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-browser.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getBrowser', + description: '/docs/references/avatars/get-browser.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -204,13 +223,20 @@ App::get('/v1/avatars/flags/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/flag') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getFlag') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-flag.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getFlag', + description: '/docs/references/avatars/get-flag.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -224,13 +250,20 @@ App::get('/v1/avatars/image') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/image') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getImage') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-image.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getImage', + description: '/docs/references/avatars/get-image.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE + )) ->param('url', '', new URL(['http', 'https']), 'Image URL which you want to crop.') ->param('width', 400, new Range(0, 2000), 'Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.', true) ->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.', true) @@ -287,13 +320,20 @@ App::get('/v1/avatars/favicon') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/favicon') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getFavicon') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-favicon.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getFavicon', + description: '/docs/references/avatars/get-favicon.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE + )) ->param('url', '', new URL(['http', 'https']), 'Website URL which you want to fetch the favicon from.') ->inject('response') ->action(function (string $url, Response $response) { @@ -430,13 +470,20 @@ App::get('/v1/avatars/qr') ->desc('Get QR code') ->groups(['api', 'avatars']) ->label('scope', 'avatars.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getQR') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-qr.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getQR', + description: '/docs/references/avatars/get-qr.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('text', '', new Text(512), 'Plain text to be converted to QR code image.') ->param('size', 400, new Range(1, 1000), 'QR code size. Pass an integer between 1 to 1000. Defaults to 400.', true) ->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true) @@ -471,13 +518,20 @@ App::get('/v1/avatars/initials') ->groups(['api', 'avatars']) ->label('scope', 'avatars.read') ->label('cache.resource', 'avatar/initials') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getInitials') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-initials.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getInitials', + description: '/docs/references/avatars/get-initials.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true) ->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -1222,4 +1276,4 @@ App::get('/v1/cards/cloud-og') ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days ->setContentType('image/png') ->file($baseImage->getImageBlob()); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 1b307b1d14..77ba67e6e1 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -1,6 +1,10 @@ <?php use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Document; @@ -21,13 +25,19 @@ App::get('/v1/console/variables') ->desc('Get variables') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'console') - ->label('sdk.method', 'variables') - ->label('sdk.description', '/docs/references/console/variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CONSOLE_VARIABLES) + ->label('sdk', new Method( + namespace: 'console', + name: 'variables', + description: '/docs/references/console/variables.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CONSOLE_VARIABLES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { $isDomainEnabled = !empty(System::getEnv('_APP_DOMAIN', '')) @@ -60,12 +70,19 @@ App::post('/v1/console/assistant') ->desc('Ask query') ->groups(['api', 'assistant']) ->label('scope', 'assistant.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'assistant') - ->label('sdk.method', 'chat') - ->label('sdk.description', '/docs/references/assistant/chat.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_TEXT) + ->label('sdk', new Method( + namespace: 'assistant', + name: 'chat', + description: '/docs/references/assistant/chat.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::TEXT + )) ->label('abuse-limit', 15) ->label('abuse-key', 'userId:{userId}') ->param('prompt', '', new Text(2000), 'Prompt. A string containing questions asked to the AI assistant.') @@ -108,4 +125,4 @@ App::post('/v1/console/assistant') curl_close($ch); $response->chunk('', true); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 347b4ebbef..b4635128c3 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -7,6 +7,10 @@ use Appwrite\Event\Event; use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Appwrite\Utopia\Database\Validator\Queries\Collections; @@ -452,13 +456,19 @@ App::post('/v1/databases') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'database.create') ->label('audits.resource', 'database/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/databases/create.md') // create this file later - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) // Model for database needs to be created + ->label('sdk', new Method( + namespace: 'databases', + name: 'create', + description: '/docs/references/databases/create.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Database name. Max length: 128 chars.') ->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) @@ -528,13 +538,19 @@ App::get('/v1/databases') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/databases/list.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'list', + description: '/docs/references/databases/list.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -584,13 +600,19 @@ App::get('/v1/databases/:databaseId') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/databases/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'get', + description: '/docs/references/databases/get.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') @@ -610,13 +632,19 @@ App::get('/v1/databases/:databaseId/logs') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/databases/get-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listLogs', + description: '/docs/references/databases/get-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -705,13 +733,19 @@ App::put('/v1/databases/:databaseId') ->label('event', 'databases.[databaseId].update') ->label('audits.event', 'database.update') ->label('audits.resource', 'database/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'update') - ->label('sdk.description', '/docs/references/databases/update.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'update', + description: '/docs/references/databases/update.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('name', null, new Text(128), 'Database name. Max length: 128 chars.') ->param('enabled', true, new Boolean(), 'Is database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) @@ -744,12 +778,19 @@ App::delete('/v1/databases/:databaseId') ->label('event', 'databases.[databaseId].delete') ->label('audits.event', 'database.delete') ->label('audits.resource', 'database/{request.databaseId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/databases/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'delete', + description: '/docs/references/databases/delete.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') @@ -793,13 +834,19 @@ App::post('/v1/databases/:databaseId/collections') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'collection.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createCollection') - ->label('sdk.description', '/docs/references/databases/create-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createCollection', + description: '/docs/references/databases/create-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') @@ -858,13 +905,19 @@ App::get('/v1/databases/:databaseId/collections') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listCollections') - ->label('sdk.description', '/docs/references/databases/list-collections.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listCollections', + description: '/docs/references/databases/list-collections.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -924,13 +977,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getCollection') - ->label('sdk.description', '/docs/references/databases/get-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getCollection', + description: '/docs/references/databases/get-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') @@ -959,13 +1018,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listCollectionLogs') - ->label('sdk.description', '/docs/references/databases/get-collection-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listCollectionLogs', + description: '/docs/references/databases/get-collection-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) @@ -1058,13 +1123,19 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->label('event', 'databases.[databaseId].collections.[collectionId].update') ->label('audits.event', 'collection.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateCollection') - ->label('sdk.description', '/docs/references/databases/update-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateCollection', + description: '/docs/references/databases/update-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') @@ -1126,12 +1197,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->label('event', 'databases.[databaseId].collections.[collectionId].delete') ->label('audits.event', 'collection.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteCollection') - ->label('sdk.description', '/docs/references/databases/delete-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteCollection', + description: '/docs/references/databases/delete-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') @@ -1182,13 +1260,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createStringAttribute') - ->label('sdk.description', '/docs/references/databases/create-string-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createStringAttribute', + description: '/docs/references/databases/create-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_STRING + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1239,13 +1322,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createEmailAttribute') - ->label('sdk.description', '/docs/references/databases/create-email-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createEmailAttribute', + description: '/docs/references/databases/create-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_EMAIL, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1282,13 +1370,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createEnumAttribute') - ->label('sdk.description', '/docs/references/databases/create-attribute-enum.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createEnumAttribute', + description: '/docs/references/databases/create-attribute-enum.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_ENUM, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1330,13 +1423,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createIpAttribute') - ->label('sdk.description', '/docs/references/databases/create-ip-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIpAttribute', + description: '/docs/references/databases/create-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_IP, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1373,13 +1471,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createUrlAttribute') - ->label('sdk.description', '/docs/references/databases/create-url-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createUrlAttribute', + description: '/docs/references/databases/create-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_URL, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1416,13 +1519,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createIntegerAttribute') - ->label('sdk.description', '/docs/references/databases/create-integer-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIntegerAttribute', + description: '/docs/references/databases/create-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_INTEGER, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1488,13 +1596,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createFloatAttribute') - ->label('sdk.description', '/docs/references/databases/create-float-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createFloatAttribute', + description: '/docs/references/databases/create-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_FLOAT, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1558,13 +1671,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createBooleanAttribute') - ->label('sdk.description', '/docs/references/databases/create-boolean-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createBooleanAttribute', + description: '/docs/references/databases/create-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_BOOLEAN, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1600,13 +1718,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createDatetimeAttribute') - ->label('sdk.description', '/docs/references/databases/create-datetime-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_DATETIME) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createDatetimeAttribute', + description: '/docs/references/databases/create-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_DATETIME, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1645,13 +1768,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createRelationshipAttribute') - ->label('sdk.description', '/docs/references/databases/create-relationship-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createRelationshipAttribute', + description: '/docs/references/databases/create-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('relatedCollectionId', '', new UID(), 'Related Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') @@ -1771,13 +1899,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listAttributes') - ->label('sdk.description', '/docs/references/databases/list-attributes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listAttributes', + description: '/docs/references/databases/list-attributes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_LIST + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) @@ -1852,23 +1985,29 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getAttribute') - ->label('sdk.description', '/docs/references/databases/get-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', [ - Response::MODEL_ATTRIBUTE_BOOLEAN, - Response::MODEL_ATTRIBUTE_INTEGER, - Response::MODEL_ATTRIBUTE_FLOAT, - Response::MODEL_ATTRIBUTE_EMAIL, - Response::MODEL_ATTRIBUTE_ENUM, - Response::MODEL_ATTRIBUTE_URL, - Response::MODEL_ATTRIBUTE_IP, - Response::MODEL_ATTRIBUTE_DATETIME, - Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING])// needs to be last, since its condition would dominate any other string attribute + ->label('sdk', new Method( + namespace: 'databases', + name: 'getAttribute', + description: '/docs/references/databases/get-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: [ + Response::MODEL_ATTRIBUTE_BOOLEAN, + Response::MODEL_ATTRIBUTE_INTEGER, + Response::MODEL_ATTRIBUTE_FLOAT, + Response::MODEL_ATTRIBUTE_EMAIL, + Response::MODEL_ATTRIBUTE_ENUM, + Response::MODEL_ATTRIBUTE_URL, + Response::MODEL_ATTRIBUTE_IP, + Response::MODEL_ATTRIBUTE_DATETIME, + Response::MODEL_ATTRIBUTE_RELATIONSHIP, + Response::MODEL_ATTRIBUTE_STRING + ] + ), + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1930,12 +2069,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateStringAttribute') - ->label('sdk.description', '/docs/references/databases/update-string-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateStringAttribute', + description: '/docs/references/databases/update-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_STRING, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1974,12 +2120,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateEmailAttribute') - ->label('sdk.description', '/docs/references/databases/update-email-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateEmailAttribute', + description: '/docs/references/databases/update-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_EMAIL, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2016,12 +2169,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateEnumAttribute') - ->label('sdk.description', '/docs/references/databases/update-enum-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateEnumAttribute', + description: '/docs/references/databases/update-enum-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_ENUM, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2060,12 +2220,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:k ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateIpAttribute') - ->label('sdk.description', '/docs/references/databases/update-ip-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateIpAttribute', + description: '/docs/references/databases/update-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_IP, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2102,12 +2269,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/: ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateUrlAttribute') - ->label('sdk.description', '/docs/references/databases/update-url-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateUrlAttribute', + description: '/docs/references/databases/update-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_URL, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2144,12 +2318,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateIntegerAttribute') - ->label('sdk.description', '/docs/references/databases/update-integer-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateIntegerAttribute', + description: '/docs/references/databases/update-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_INTEGER, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2196,12 +2377,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateFloatAttribute') - ->label('sdk.description', '/docs/references/databases/update-float-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateFloatAttribute', + description: '/docs/references/databases/update-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_FLOAT, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2248,12 +2436,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boole ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateBooleanAttribute') - ->label('sdk.description', '/docs/references/databases/update-boolean-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateBooleanAttribute', + description: '/docs/references/databases/update-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_BOOLEAN, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2289,12 +2484,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datet ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateDatetimeAttribute') - ->label('sdk.description', '/docs/references/databases/update-datetime-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_DATETIME) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateDatetimeAttribute', + description: '/docs/references/databases/update-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_DATETIME, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2330,12 +2532,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateRelationshipAttribute') - ->label('sdk.description', '/docs/references/databases/update-relationship-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateRelationshipAttribute', + description: '/docs/references/databases/update-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2388,12 +2597,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteAttribute') - ->label('sdk.description', '/docs/references/databases/delete-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteAttribute', + description: '/docs/references/databases/delete-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2502,13 +2718,19 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createIndex') - ->label('sdk.description', '/docs/references/databases/create-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIndex', + description: '/docs/references/databases/create-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') @@ -2666,13 +2888,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listIndexes') - ->label('sdk.description', '/docs/references/databases/list-indexes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listIndexes', + description: '/docs/references/databases/list-indexes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INDEX_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) @@ -2742,13 +2970,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getIndex') - ->label('sdk.description', '/docs/references/databases/get-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getIndex', + description: '/docs/references/databases/get-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') @@ -2785,12 +3019,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update') ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteIndex') - ->label('sdk.description', '/docs/references/databases/delete-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteIndex', + description: '/docs/references/databases/delete-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Index Key.') @@ -2853,15 +3094,24 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createDocument') - ->label('sdk.description', '/docs/references/databases/create-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label( + 'sdk', + [ + new Method( + namespace: 'databases', + name: 'createDocument', + description: '/docs/references/databases/create-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + ) + ] + ) ->param('databaseId', '', new UID(), 'Database ID.') ->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.') @@ -3110,14 +3360,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listDocuments') - ->label('sdk.description', '/docs/references/databases/list-documents.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') + ->label('sdk', new Method( + namespace: 'databases', + name: 'listDocuments', + description: '/docs/references/databases/list-documents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) @@ -3283,15 +3538,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getDocument') - ->label('sdk.description', '/docs/references/databases/get-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + name: 'getDocument', + description: '/docs/references/databases/get-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('documentId', '', new UID(), 'Document ID.') @@ -3392,13 +3651,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listDocumentLogs') - ->label('sdk.description', '/docs/references/databases/get-document-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listDocumentLogs', + description: '/docs/references/databases/get-document-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') @@ -3504,15 +3769,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateDocument') - ->label('sdk.description', '/docs/references/databases/update-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateDocument', + description: '/docs/references/databases/update-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') @@ -3756,14 +4025,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteDocument') - ->label('sdk.description', '/docs/references/databases/delete-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteDocument', + description: '/docs/references/databases/delete-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('documentId', '', new UID(), 'Document ID.') @@ -3873,12 +4147,19 @@ App::get('/v1/databases/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_DATABASES, + ) + ], + contentType: ContentType::JSON + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) ->inject('response') ->inject('dbForProject') @@ -3955,12 +4236,19 @@ App::get('/v1/databases/:databaseId/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getDatabaseUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getDatabaseUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_DATABASE, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) ->inject('response') @@ -4043,12 +4331,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getCollectionUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getCollectionUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_COLLECTION, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->param('collectionId', '', new UID(), 'Collection ID.') @@ -4120,4 +4415,4 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') 'documentsTotal' => $usage[$metrics[0]]['total'], 'documents' => $usage[$metrics[0]]['data'], ]), Response::MODEL_USAGE_COLLECTION); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d4d5fc64cf..9b6f92ed5b 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -14,6 +14,11 @@ use Appwrite\Functions\Validator\Headers; use Appwrite\Functions\Validator\RuntimeSpecification; use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Platform\Tasks\ScheduleExecutions; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Task\Validator\Cron; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Deployments; @@ -142,13 +147,18 @@ App::post('/v1/functions') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'function.create') ->label('audits.resource', 'function/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/functions/create-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'create', + description: '/docs/references/functions/create-function.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_FUNCTION, + ) + ], + )) ->param('functionId', '', new CustomId(), 'Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') @@ -434,13 +444,18 @@ App::get('/v1/functions') ->desc('List functions') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/functions/list-functions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'list', + description: '/docs/references/functions/list-functions.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION_LIST, + ) + ] + )) ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -495,13 +510,18 @@ App::get('/v1/functions/runtimes') ->desc('List runtimes') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listRuntimes') - ->label('sdk.description', '/docs/references/functions/list-runtimes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_RUNTIME_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listRuntimes', + description: '/docs/references/functions/list-runtimes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_RUNTIME_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $runtimes = Config::getParam('runtimes'); @@ -529,13 +549,18 @@ App::get('/v1/functions/specifications') ->desc('List available function runtime specifications') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listSpecifications') - ->label('sdk.description', '/docs/references/functions/list-specifications.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SPECIFICATION_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listSpecifications', + description: '/docs/references/functions/list-specifications.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SPECIFICATION_LIST, + ) + ] + )) ->inject('response') ->inject('plan') ->action(function (Response $response, array $plan) { @@ -566,13 +591,18 @@ App::get('/v1/functions/:functionId') ->desc('Get function') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/functions/get-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'get', + description: '/docs/references/functions/get-function.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->inject('response') ->inject('dbForProject') @@ -591,12 +621,18 @@ App::get('/v1/functions/:functionId/usage') ->groups(['api', 'functions', 'usage']) ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getFunctionUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getFunctionUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_FUNCTION, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') @@ -696,12 +732,18 @@ App::get('/v1/functions/usage') ->groups(['api', 'functions']) ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_FUNCTIONS, + ) + ] + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') @@ -799,13 +841,18 @@ App::put('/v1/functions/:functionId') ->label('event', 'functions.[functionId].update') ->label('audits.event', 'function.update') ->label('audits.resource', 'function/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'update') - ->label('sdk.description', '/docs/references/functions/update-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'update', + description: '/docs/references/functions/update-function.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.', true) @@ -999,13 +1046,20 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId/download') ->desc('Download deployment') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getDeploymentDownload') - ->label('sdk.description', '/docs/references/functions/get-deployment-download.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'functions', + name: 'getDeploymentDownload', + description: '/docs/references/functions/get-deployment-download.md', + auth: [AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::ANY, + type: MethodType::LOCATION + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') @@ -1088,13 +1142,18 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ->label('event', 'functions.[functionId].deployments.[deploymentId].update') ->label('audits.event', 'deployment.update') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateDeployment') - ->label('sdk.description', '/docs/references/functions/update-function-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateDeployment', + description: '/docs/references/functions/update-function-deployment.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') @@ -1151,12 +1210,19 @@ App::delete('/v1/functions/:functionId') ->label('event', 'functions.[functionId].delete') ->label('audits.event', 'function.delete') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/functions/delete-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'delete', + description: '/docs/references/functions/delete-function.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('functionId', '', new UID(), 'Function ID.') ->inject('response') ->inject('dbForProject') @@ -1199,16 +1265,21 @@ App::post('/v1/functions/:functionId/deployments') ->label('event', 'functions.[functionId].deployments.[deploymentId].create') ->label('audits.event', 'deployment.create') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createDeployment') - ->label('sdk.methodType', 'upload') - ->label('sdk.description', '/docs/references/functions/create-deployment.md') - ->label('sdk.packaging', true) - ->label('sdk.request.type', 'multipart/form-data') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT) + ->label('sdk', new Method( + namespace: 'functions', + name: 'createDeployment', + description: '/docs/references/functions/create-deployment.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + requestType: 'multipart/form-data', + type: MethodType::UPLOAD, + packaging: true, + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('entrypoint', null, new Text(1028), 'Entrypoint File.', true) ->param('commands', null, new Text(8192, 0), 'Build Commands.', true) @@ -1416,13 +1487,18 @@ App::get('/v1/functions/:functionId/deployments') ->desc('List deployments') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listDeployments') - ->label('sdk.description', '/docs/references/functions/list-deployments.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listDeployments', + description: '/docs/references/functions/list-deployments.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT_LIST, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -1500,13 +1576,18 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') ->desc('Get deployment') ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getDeployment') - ->label('sdk.description', '/docs/references/functions/get-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getDeployment', + description: '/docs/references/functions/get-deployment.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') @@ -1547,12 +1628,19 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') ->label('event', 'functions.[functionId].deployments.[deploymentId].delete') ->label('audits.event', 'deployment.delete') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteDeployment') - ->label('sdk.description', '/docs/references/functions/delete-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteDeployment', + description: '/docs/references/functions/delete-deployment.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') @@ -1613,11 +1701,18 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/build') ->label('event', 'functions.[functionId].deployments.[deploymentId].update') ->label('audits.event', 'deployment.update') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createBuild') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'createBuild', + description: '', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->param('buildId', '', new UID(), 'Build unique ID.', true) // added as optional param for backward compatibility @@ -1681,12 +1776,18 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'deployment.update') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateDeploymentBuild') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUILD) + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateDeploymentBuild', + description: '', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUILD, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') @@ -1770,15 +1871,20 @@ App::post('/v1/functions/:functionId/executions') ->label('scope', 'execution.write') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('event', 'functions.[functionId].executions.[executionId].create') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createExecution') - ->label('sdk.description', '/docs/references/functions/create-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_MULTIPART) - ->label('sdk.response.model', Response::MODEL_EXECUTION) - ->label('sdk.request.type', Response::CONTENT_TYPE_JSON) + ->label('sdk', new Method( + namespace: 'functions', + name: 'createExecution', + description: '/docs/references/functions/create-execution.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_EXECUTION, + ) + ], + contentType: ContentType::MULTIPART, + requestType: 'application/json', + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true) ->param('async', false, new Boolean(true), 'Execute code in the background. Default value is false.', true) @@ -2173,13 +2279,18 @@ App::get('/v1/functions/:functionId/executions') ->desc('List executions') ->label('scope', 'execution.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listExecutions') - ->label('sdk.description', '/docs/references/functions/list-executions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EXECUTION_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listExecutions', + description: '/docs/references/functions/list-executions.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION_LIST, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Executions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -2261,13 +2372,18 @@ App::get('/v1/functions/:functionId/executions/:executionId') ->desc('Get execution') ->label('scope', 'execution.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getExecution') - ->label('sdk.description', '/docs/references/functions/get-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EXECUTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getExecution', + description: '/docs/references/functions/get-execution.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION, + ) + ] + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') @@ -2312,12 +2428,19 @@ App::delete('/v1/functions/:functionId/executions/:executionId') ->label('event', 'functions.[functionId].executions.[executionId].delete') ->label('audits.event', 'executions.delete') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteExecution') - ->label('sdk.description', '/docs/references/functions/delete-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteExecution', + description: '/docs/references/functions/delete-execution.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('functionId', '', new UID(), 'Function ID.') ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') @@ -2382,13 +2505,18 @@ App::post('/v1/functions/:functionId/variables') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'variable.create') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createVariable') - ->label('sdk.description', '/docs/references/functions/create-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'createVariable', + description: '/docs/references/functions/create-variable.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('functionId', '', new UID(), 'Function unique ID.', false) ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) @@ -2445,13 +2573,21 @@ App::get('/v1/functions/:functionId/variables') ->groups(['api', 'functions']) ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listVariables') - ->label('sdk.description', '/docs/references/functions/list-variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE_LIST) + ->label( + 'sdk', + new Method( + namespace: 'functions', + name: 'listVariables', + description: '/docs/references/functions/list-variables.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE_LIST, + ) + ], + ) + ) ->param('functionId', '', new UID(), 'Function unique ID.', false) ->inject('response') ->inject('dbForProject') @@ -2473,13 +2609,21 @@ App::get('/v1/functions/:functionId/variables/:variableId') ->groups(['api', 'functions']) ->label('scope', 'functions.read') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getVariable') - ->label('sdk.description', '/docs/references/functions/get-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label( + 'sdk', + new Method( + namespace: 'functions', + name: 'getVariable', + description: '/docs/references/functions/get-variable.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ], + ) + ) ->param('functionId', '', new UID(), 'Function unique ID.', false) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') @@ -2515,13 +2659,18 @@ App::put('/v1/functions/:functionId/variables/:variableId') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'variable.update') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateVariable') - ->label('sdk.description', '/docs/references/functions/update-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateVariable', + description: '/docs/references/functions/update-variable.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('functionId', '', new UID(), 'Function unique ID.', false) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) @@ -2577,12 +2726,19 @@ App::delete('/v1/functions/:functionId/variables/:variableId') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) ->label('audits.event', 'variable.delete') ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteVariable') - ->label('sdk.description', '/docs/references/functions/delete-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteVariable', + description: '/docs/references/functions/delete-variable.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('functionId', '', new UID(), 'Function unique ID.', false) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') @@ -2624,13 +2780,18 @@ App::get('/v1/functions/templates') ->desc('List function templates') ->label('scope', 'public') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listTemplates') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.description', '/docs/references/functions/list-templates.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEMPLATE_FUNCTION_LIST) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listTemplates', + description: '/docs/references/functions/list-templates.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_FUNCTION_LIST, + ) + ] + )) ->param('runtimes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('runtimes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of runtimes allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' runtimes are allowed.', true) ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) @@ -2662,13 +2823,18 @@ App::get('/v1/functions/templates/:templateId') ->desc('Get function template') ->label('scope', 'public') ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getTemplate') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.description', '/docs/references/functions/get-template.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEMPLATE_FUNCTION) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getTemplate', + description: '/docs/references/functions/get-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_FUNCTION, + ) + ] + )) ->param('templateId', '', new Text(128), 'Template ID.') ->inject('response') ->action(function (string $templateId, Response $response) { @@ -2685,4 +2851,4 @@ App::get('/v1/functions/templates/:templateId') } $response->dynamic(new Document($template), Response::MODEL_TEMPLATE_FUNCTION); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index f79f433b5c..80a17db7cb 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -5,6 +5,10 @@ use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\GraphQL\Promises\Adapter; use Appwrite\GraphQL\Schema; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use GraphQL\Error\DebugFlag; @@ -38,13 +42,19 @@ App::get('/v1/graphql') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.hide', true) - ->label('sdk.description', '/docs/references/graphql/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'get', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + hide: true, + description: '/docs/references/graphql/get.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ] + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->param('query', '', new Text(0, 0), 'The query to execute.') @@ -78,17 +88,22 @@ App::post('/v1/graphql/mutation') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.method', 'mutation') - ->label('sdk.methodType', 'graphql') - ->label('sdk.description', '/docs/references/graphql/post.md') - ->label('sdk.parameters', [ - 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], - ]) - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'mutation', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + description: '/docs/references/graphql/post.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ], + type: MethodType::GRAPHQL, + additionalParameters: [ + 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], + ], + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->inject('request') @@ -123,17 +138,22 @@ App::post('/v1/graphql') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.method', 'query') - ->label('sdk.methodType', 'graphql') - ->label('sdk.description', '/docs/references/graphql/post.md') - ->label('sdk.parameters', [ - 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], - ]) - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'query', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + description: '/docs/references/graphql/post.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ], + type: MethodType::GRAPHQL, + additionalParameters: [ + 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], + ], + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->inject('request') @@ -311,4 +331,4 @@ App::shutdown() ->inject('project') ->action(function (Document $project) { Schema::setDirty($project->getId()); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 60a8c0ca97..787bc71ac8 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -3,6 +3,10 @@ use Appwrite\ClamAV\Network; use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; @@ -26,13 +30,19 @@ App::get('/v1/health') ->desc('Get HTTP') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/health/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + namespace: 'health', + name: 'get', + auth: [AuthType::KEY], + description: '/docs/references/health/get.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -49,9 +59,6 @@ App::get('/v1/health/version') ->desc('Get version') ->groups(['api', 'health']) ->label('scope', 'public') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_VERSION) ->inject('response') ->action(function (Response $response) { $response->dynamic(new Document([ 'version' => APP_VERSION_STABLE ]), Response::MODEL_HEALTH_VERSION); @@ -61,13 +68,19 @@ App::get('/v1/health/db') ->desc('Get DB') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getDB') - ->label('sdk.description', '/docs/references/health/get-db.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getDB', + description: '/docs/references/health/get-db.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -115,13 +128,19 @@ App::get('/v1/health/cache') ->desc('Get cache') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getCache') - ->label('sdk.description', '/docs/references/health/get-cache.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getCache', + description: '/docs/references/health/get-cache.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -173,13 +192,19 @@ App::get('/v1/health/queue') ->desc('Get queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueue') - ->label('sdk.description', '/docs/references/health/get-queue.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueue', + description: '/docs/references/health/get-queue.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -230,13 +255,19 @@ App::get('/v1/health/pubsub') ->desc('Get pubsub') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getPubSub') - ->label('sdk.description', '/docs/references/health/get-pubsub.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getPubSub', + description: '/docs/references/health/get-pubsub.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -288,13 +319,19 @@ App::get('/v1/health/time') ->desc('Get time') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getTime') - ->label('sdk.description', '/docs/references/health/get-time.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_TIME) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getTime', + description: '/docs/references/health/get-time.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_TIME, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -345,13 +382,19 @@ App::get('/v1/health/queue/webhooks') ->desc('Get webhooks queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueWebhooks') - ->label('sdk.description', '/docs/references/health/get-queue-webhooks.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueWebhooks', + description: '/docs/references/health/get-queue-webhooks.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -372,13 +415,19 @@ App::get('/v1/health/queue/logs') ->desc('Get logs queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueLogs') - ->label('sdk.description', '/docs/references/health/get-queue-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueLogs', + description: '/docs/references/health/get-queue-logs.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -399,13 +448,19 @@ App::get('/v1/health/certificate') ->desc('Get the SSL certificate for a domain') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getCertificate') - ->label('sdk.description', '/docs/references/health/get-certificate.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_CERTIFICATE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getCertificate', + description: '/docs/references/health/get-certificate.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_CERTIFICATE, + ) + ], + contentType: ContentType::JSON + )) ->param('domain', null, new Multiple([new Domain(), new PublicDomain()]), Multiple::TYPE_STRING, 'Domain name') ->inject('response') ->action(function (string $domain, Response $response) { @@ -449,13 +504,19 @@ App::get('/v1/health/queue/certificates') ->desc('Get certificates queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueCertificates') - ->label('sdk.description', '/docs/references/health/get-queue-certificates.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueCertificates', + description: '/docs/references/health/get-queue-certificates.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -476,13 +537,19 @@ App::get('/v1/health/queue/builds') ->desc('Get builds queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueBuilds') - ->label('sdk.description', '/docs/references/health/get-queue-builds.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueBuilds', + description: '/docs/references/health/get-queue-builds.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -503,13 +570,19 @@ App::get('/v1/health/queue/databases') ->desc('Get databases queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueDatabases') - ->label('sdk.description', '/docs/references/health/get-queue-databases.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueDatabases', + description: '/docs/references/health/get-queue-databases.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('name', 'database_db_main', new Text(256), 'Queue name for which to check the queue size', true) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') @@ -531,13 +604,19 @@ App::get('/v1/health/queue/deletes') ->desc('Get deletes queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueDeletes') - ->label('sdk.description', '/docs/references/health/get-queue-deletes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueDeletes', + description: '/docs/references/health/get-queue-deletes.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -558,13 +637,19 @@ App::get('/v1/health/queue/mails') ->desc('Get mails queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMails') - ->label('sdk.description', '/docs/references/health/get-queue-mails.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMails', + description: '/docs/references/health/get-queue-mails.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -585,13 +670,19 @@ App::get('/v1/health/queue/messaging') ->desc('Get messaging queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMessaging') - ->label('sdk.description', '/docs/references/health/get-queue-messaging.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMessaging', + description: '/docs/references/health/get-queue-messaging.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -612,13 +703,19 @@ App::get('/v1/health/queue/migrations') ->desc('Get migrations queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMigrations') - ->label('sdk.description', '/docs/references/health/get-queue-migrations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMigrations', + description: '/docs/references/health/get-queue-migrations.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -639,13 +736,19 @@ App::get('/v1/health/queue/functions') ->desc('Get functions queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueFunctions') - ->label('sdk.description', '/docs/references/health/get-queue-functions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueFunctions', + description: '/docs/references/health/get-queue-functions.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -666,13 +769,19 @@ App::get('/v1/health/queue/usage') ->desc('Get usage queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsage') - ->label('sdk.description', '/docs/references/health/get-queue-usage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueUsage', + description: '/docs/references/health/get-queue-usage.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -693,13 +802,19 @@ App::get('/v1/health/queue/usage-dump') ->desc('Get usage dump queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsageDump') - ->label('sdk.description', '/docs/references/health/get-queue-usage-dump.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueUsageDump', + description: '/docs/references/health/get-queue-usage-dump.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('queue') ->inject('response') @@ -720,13 +835,19 @@ App::get('/v1/health/storage/local') ->desc('Get local storage') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getStorageLocal') - ->label('sdk.description', '/docs/references/health/get-storage-local.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getStorageLocal', + description: '/docs/references/health/get-storage-local.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -763,13 +884,19 @@ App::get('/v1/health/storage') ->desc('Get storage') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getStorage') - ->label('sdk.description', '/docs/references/health/get-storage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getStorage', + description: '/docs/references/health/get-storage.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('deviceForFiles') ->inject('deviceForFunctions') @@ -804,13 +931,19 @@ App::get('/v1/health/anti-virus') ->desc('Get antivirus') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getAntivirus') - ->label('sdk.description', '/docs/references/health/get-storage-anti-virus.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_ANTIVIRUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getAntivirus', + description: '/docs/references/health/get-storage-anti-virus.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_ANTIVIRUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -843,9 +976,19 @@ App::get('/v1/health/queue/failed/:name') ->desc('Get number of failed queue jobs') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getFailedJobs') + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getFailedJobs', + description: '/docs/references/health/get-failed-queue-jobs.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('name', '', new WhiteList([ Event::DATABASE_QUEUE_NAME, Event::DELETE_QUEUE_NAME, @@ -861,10 +1004,6 @@ App::get('/v1/health/queue/failed/:name') Event::MIGRATIONS_QUEUE_NAME ]), 'The name of the queue') ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->label('sdk.description', '/docs/references/health/get-failed-queue-jobs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') ->inject('queue') ->action(function (string $name, int|string $threshold, Response $response, Connection $queue) { @@ -915,4 +1054,4 @@ App::get('/v1/health/stats') // Currently only used internally 'memory_used_peak_human' => $cacheStats['used_memory_peak_human'] ?? 0, ], ]); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/locale.php b/app/controllers/api/locale.php index 1f042d2239..65f719f914 100644 --- a/app/controllers/api/locale.php +++ b/app/controllers/api/locale.php @@ -1,5 +1,8 @@ <?php +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -12,15 +15,18 @@ App::get('/v1/locale') ->desc('Get user locale') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/locale/get-locale.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOCALE) - ->label('sdk.offline.model', '/localed') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'locale', + name: 'get', + description: '/docs/references/locale/get-locale.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOCALE, + ) + ] + )) ->inject('request') ->inject('response') ->inject('locale') @@ -72,15 +78,18 @@ App::get('/v1/locale/codes') ->desc('List locale codes') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCodes') - ->label('sdk.description', '/docs/references/locale/list-locale-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOCALE_CODE_LIST) - ->label('sdk.offline.model', '/locale/localeCode') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCodes', + description: '/docs/references/locale/list-locale-codes.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOCALE_CODE_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $codes = Config::getParam('locale-codes'); @@ -94,15 +103,18 @@ App::get('/v1/locale/countries') ->desc('List countries') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountries') - ->label('sdk.description', '/docs/references/locale/list-countries.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COUNTRY_LIST) - ->label('sdk.offline.model', '/locale/countries') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountries', + description: '/docs/references/locale/list-countries.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COUNTRY_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -127,15 +139,18 @@ App::get('/v1/locale/countries/eu') ->desc('List EU countries') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountriesEU') - ->label('sdk.description', '/docs/references/locale/list-countries-eu.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COUNTRY_LIST) - ->label('sdk.offline.model', '/locale/countries/eu') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountriesEU', + description: '/docs/references/locale/list-countries-eu.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COUNTRY_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -162,15 +177,18 @@ App::get('/v1/locale/countries/phones') ->desc('List countries phone codes') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountriesPhones') - ->label('sdk.description', '/docs/references/locale/list-countries-phones.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PHONE_LIST) - ->label('sdk.offline.model', '/locale/countries/phones') - ->label('sdk.offline.response.key', 'countryCode') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountriesPhones', + description: '/docs/references/locale/list-countries-phones.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PHONE_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -196,15 +214,18 @@ App::get('/v1/locale/continents') ->desc('List continents') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listContinents') - ->label('sdk.description', '/docs/references/locale/list-continents.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CONTINENT_LIST) - ->label('sdk.offline.model', '/locale/continents') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listContinents', + description: '/docs/references/locale/list-continents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CONTINENT_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -228,15 +249,18 @@ App::get('/v1/locale/currencies') ->desc('List currencies') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCurrencies') - ->label('sdk.description', '/docs/references/locale/list-currencies.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CURRENCY_LIST) - ->label('sdk.offline.model', '/locale/currencies') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCurrencies', + description: '/docs/references/locale/list-currencies.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CURRENCY_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $list = Config::getParam('locale-currencies'); @@ -251,15 +275,18 @@ App::get('/v1/locale/languages') ->desc('List languages') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listLanguages') - ->label('sdk.description', '/docs/references/locale/list-languages.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LANGUAGE_LIST) - ->label('sdk.offline.model', '/locale/languages') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listLanguages', + description: '/docs/references/locale/list-languages.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LANGUAGE_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $list = Config::getParam('locale-languages'); @@ -267,4 +294,4 @@ App::get('/v1/locale/languages') $list = array_map(fn ($node) => new Document($node), $list); $response->dynamic(new Document(['languages' => $list, 'total' => \count($list)]), Response::MODEL_LANGUAGE_LIST); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e7748484ba..c80da75801 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -11,6 +11,10 @@ use Appwrite\Messaging\Status as MessageStatus; use Appwrite\Network\Validator\Email; use Appwrite\Permission; use Appwrite\Role; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CompoundUID; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Messages; @@ -57,13 +61,18 @@ App::post('/v1/messaging/providers/mailgun') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createMailgunProvider') - ->label('sdk.description', '/docs/references/messaging/create-mailgun-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createMailgunProvider', + description: '/docs/references/messaging/create-mailgun-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) @@ -145,13 +154,18 @@ App::post('/v1/messaging/providers/sendgrid') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSendgridProvider') - ->label('sdk.description', '/docs/references/messaging/create-sendgrid-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSendgridProvider', + description: '/docs/references/messaging/create-sendgrid-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) @@ -221,13 +235,18 @@ App::post('/v1/messaging/providers/smtp') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSmtpProvider') - ->label('sdk.description', '/docs/references/messaging/create-smtp-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSmtpProvider', + description: '/docs/references/messaging/create-smtp-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.') @@ -310,13 +329,18 @@ App::post('/v1/messaging/providers/msg91') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) ->label('event', 'providers.[providerId].create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createMsg91Provider') - ->label('sdk.description', '/docs/references/messaging/create-msg91-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createMsg91Provider', + description: '/docs/references/messaging/create-msg91-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('templateId', '', new Text(0), 'Msg91 template ID', true) @@ -387,13 +411,18 @@ App::post('/v1/messaging/providers/telesign') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTelesignProvider') - ->label('sdk.description', '/docs/references/messaging/create-telesign-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTelesignProvider', + description: '/docs/references/messaging/create-telesign-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -465,13 +494,18 @@ App::post('/v1/messaging/providers/textmagic') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTextmagicProvider') - ->label('sdk.description', '/docs/references/messaging/create-textmagic-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTextmagicProvider', + description: '/docs/references/messaging/create-textmagic-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -543,13 +577,18 @@ App::post('/v1/messaging/providers/twilio') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTwilioProvider') - ->label('sdk.description', '/docs/references/messaging/create-twilio-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTwilioProvider', + description: '/docs/references/messaging/create-twilio-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -621,13 +660,18 @@ App::post('/v1/messaging/providers/vonage') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createVonageProvider') - ->label('sdk.description', '/docs/references/messaging/create-vonage-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createVonageProvider', + description: '/docs/references/messaging/create-vonage-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -699,13 +743,18 @@ App::post('/v1/messaging/providers/fcm') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createFcmProvider') - ->label('sdk.description', '/docs/references/messaging/create-fcm-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createFcmProvider', + description: '/docs/references/messaging/create-fcm-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('serviceAccountJSON', null, new JSON(), 'FCM service account JSON.', true) @@ -763,13 +812,18 @@ App::post('/v1/messaging/providers/apns') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createApnsProvider') - ->label('sdk.description', '/docs/references/messaging/create-apns-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createApnsProvider', + description: '/docs/references/messaging/create-apns-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Provider name.') ->param('authKey', '', new Text(0), 'APNS authentication key.', true) @@ -847,13 +901,18 @@ App::get('/v1/messaging/providers') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listProviders') - ->label('sdk.description', '/docs/references/messaging/list-providers.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listProviders', + description: '/docs/references/messaging/list-providers.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_LIST, + ) + ] + )) ->param('queries', [], new Providers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -904,13 +963,18 @@ App::get('/v1/messaging/providers/:providerId/logs') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listProviderLogs') - ->label('sdk.description', '/docs/references/messaging/list-provider-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listProviderLogs', + description: '/docs/references/messaging/list-provider-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -993,13 +1057,18 @@ App::get('/v1/messaging/providers/:providerId') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getProvider') - ->label('sdk.description', '/docs/references/messaging/get-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getProvider', + description: '/docs/references/messaging/get-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') @@ -1021,13 +1090,18 @@ App::patch('/v1/messaging/providers/mailgun/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateMailgunProvider') - ->label('sdk.description', '/docs/references/messaging/update-mailgun-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateMailgunProvider', + description: '/docs/references/messaging/update-mailgun-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) @@ -1128,13 +1202,18 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSendgridProvider') - ->label('sdk.description', '/docs/references/messaging/update-sendgrid-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSendgridProvider', + description: '/docs/references/messaging/update-sendgrid-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1220,13 +1299,18 @@ App::patch('/v1/messaging/providers/smtp/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSmtpProvider') - ->label('sdk.description', '/docs/references/messaging/update-smtp-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSmtpProvider', + description: '/docs/references/messaging/update-smtp-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.', true) @@ -1343,13 +1427,18 @@ App::patch('/v1/messaging/providers/msg91/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateMsg91Provider') - ->label('sdk.description', '/docs/references/messaging/update-msg91-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateMsg91Provider', + description: '/docs/references/messaging/update-msg91-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1424,13 +1513,18 @@ App::patch('/v1/messaging/providers/telesign/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTelesignProvider') - ->label('sdk.description', '/docs/references/messaging/update-telesign-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTelesignProvider', + description: '/docs/references/messaging/update-telesign-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1507,13 +1601,18 @@ App::patch('/v1/messaging/providers/textmagic/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTextmagicProvider') - ->label('sdk.description', '/docs/references/messaging/update-textmagic-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTextmagicProvider', + description: '/docs/references/messaging/update-textmagic-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1590,13 +1689,18 @@ App::patch('/v1/messaging/providers/twilio/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTwilioProvider') - ->label('sdk.description', '/docs/references/messaging/update-twilio-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTwilioProvider', + description: '/docs/references/messaging/update-twilio-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1673,13 +1777,18 @@ App::patch('/v1/messaging/providers/vonage/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateVonageProvider') - ->label('sdk.description', '/docs/references/messaging/update-vonage-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateVonageProvider', + description: '/docs/references/messaging/update-vonage-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1756,13 +1865,18 @@ App::patch('/v1/messaging/providers/fcm/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateFcmProvider') - ->label('sdk.description', '/docs/references/messaging/update-fcm-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateFcmProvider', + description: '/docs/references/messaging/update-fcm-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1826,13 +1940,18 @@ App::patch('/v1/messaging/providers/apns/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateApnsProvider') - ->label('sdk.description', '/docs/references/messaging/update-apns-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateApnsProvider', + description: '/docs/references/messaging/update-apns-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1922,13 +2041,19 @@ App::delete('/v1/messaging/providers/:providerId') ->label('event', 'providers.[providerId].delete') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteProvider') - ->label('sdk.description', '/docs/references/messaging/delete-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteProvider', + description: '/docs/references/messaging/delete-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('providerId', '', new UID(), 'Provider ID.') ->inject('queueForEvents') ->inject('dbForProject') @@ -1958,13 +2083,18 @@ App::post('/v1/messaging/topics') ->label('event', 'topics.[topicId].create') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTopic') - ->label('sdk.description', '/docs/references/messaging/create-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTopic', + description: '/docs/references/messaging/create-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new CustomId(), 'Topic ID. Choose a custom Topic ID or a new Topic ID.') ->param('name', '', new Text(128), 'Topic Name.') ->param('subscribe', [Role::users()], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) @@ -1999,13 +2129,18 @@ App::get('/v1/messaging/topics') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTopics') - ->label('sdk.description', '/docs/references/messaging/list-topics.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTopics', + description: '/docs/references/messaging/list-topics.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC_LIST, + ) + ] + )) ->param('queries', [], new Topics(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -2056,13 +2191,18 @@ App::get('/v1/messaging/topics/:topicId/logs') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTopicLogs') - ->label('sdk.description', '/docs/references/messaging/list-topic-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTopicLogs', + description: '/docs/references/messaging/list-topic-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -2146,13 +2286,18 @@ App::get('/v1/messaging/topics/:topicId') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getTopic') - ->label('sdk.description', '/docs/references/messaging/get-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getTopic', + description: '/docs/references/messaging/get-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->inject('dbForProject') ->inject('response') @@ -2175,13 +2320,18 @@ App::patch('/v1/messaging/topics/:topicId') ->label('event', 'topics.[topicId].update') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTopic') - ->label('sdk.description', '/docs/references/messaging/update-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTopic', + description: '/docs/references/messaging/update-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('name', null, new Text(128), 'Topic Name.', true) ->param('subscribe', null, new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) @@ -2220,13 +2370,19 @@ App::delete('/v1/messaging/topics/:topicId') ->label('event', 'topics.[topicId].delete') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteTopic') - ->label('sdk.description', '/docs/references/messaging/delete-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteTopic', + description: '/docs/references/messaging/delete-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('topicId', '', new UID(), 'Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') @@ -2261,13 +2417,18 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->label('event', 'topics.[topicId].subscribers.[subscriberId].create') ->label('scope', 'subscribers.write') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_JWT, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSubscriber') - ->label('sdk.description', '/docs/references/messaging/create-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSubscriber', + description: '/docs/references/messaging/create-subscriber.md', + auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SUBSCRIBER, + ) + ] + )) ->param('subscriberId', '', new CustomId(), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.') ->param('topicId', '', new UID(), 'Topic ID. The topic ID to subscribe to.') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') @@ -2355,13 +2516,18 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listSubscribers') - ->label('sdk.description', '/docs/references/messaging/list-subscribers.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listSubscribers', + description: '/docs/references/messaging/list-subscribers.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SUBSCRIBER_LIST, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('queries', [], new Subscribers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -2435,13 +2601,18 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listSubscriberLogs') - ->label('sdk.description', '/docs/references/messaging/list-subscriber-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listSubscriberLogs', + description: '/docs/references/messaging/list-subscriber-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -2525,13 +2696,18 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getSubscriber') - ->label('sdk.description', '/docs/references/messaging/get-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getSubscriber', + description: '/docs/references/messaging/get-subscriber.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SUBSCRIBER, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') @@ -2568,13 +2744,19 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->label('event', 'topics.[topicId].subscribers.[subscriberId].delete') ->label('scope', 'subscribers.write') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_JWT, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteSubscriber') - ->label('sdk.description', '/docs/references/messaging/delete-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteSubscriber', + description: '/docs/references/messaging/delete-subscriber.md', + auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') @@ -2628,13 +2810,18 @@ App::post('/v1/messaging/messages/email') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createEmail') - ->label('sdk.description', '/docs/references/messaging/create-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createEmail', + description: '/docs/references/messaging/create-email.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('subject', '', new Text(998), 'Email Subject.') ->param('content', '', new Text(64230), 'Email Content.') @@ -2781,13 +2968,18 @@ App::post('/v1/messaging/messages/sms') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSms') - ->label('sdk.description', '/docs/references/messaging/create-sms.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSms', + description: '/docs/references/messaging/create-sms.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('content', '', new Text(64230), 'SMS Content.') ->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true) @@ -2898,13 +3090,18 @@ App::post('/v1/messaging/messages/push') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createPush') - ->label('sdk.description', '/docs/references/messaging/create-push.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createPush', + description: '/docs/references/messaging/create-push.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('title', '', new Text(256), 'Title for push notification.', true) ->param('body', '', new Text(64230), 'Body for push notification.', true) @@ -3107,13 +3304,18 @@ App::get('/v1/messaging/messages') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listMessages') - ->label('sdk.description', '/docs/references/messaging/list-messages.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listMessages', + description: '/docs/references/messaging/list-messages.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE_LIST, + ) + ], + )) ->param('queries', [], new Messages(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -3164,13 +3366,18 @@ App::get('/v1/messaging/messages/:messageId/logs') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listMessageLogs') - ->label('sdk.description', '/docs/references/messaging/list-message-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listMessageLogs', + description: '/docs/references/messaging/list-message-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -3254,13 +3461,18 @@ App::get('/v1/messaging/messages/:messageId/targets') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTargets') - ->label('sdk.description', '/docs/references/messaging/list-message-targets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTargets', + description: '/docs/references/messaging/list-message-targets.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET_LIST, + ) + ], + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Targets::ALLOWED_ATTRIBUTES), true) ->inject('response') @@ -3325,13 +3537,18 @@ App::get('/v1/messaging/messages/:messageId') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getMessage') - ->label('sdk.description', '/docs/references/messaging/get-message.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getMessage', + description: '/docs/references/messaging/get-message.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') ->inject('response') @@ -3353,13 +3570,18 @@ App::patch('/v1/messaging/messages/email/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/messaging/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateEmail', + description: '/docs/references/messaging/update-email.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3554,13 +3776,18 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSms') - ->label('sdk.description', '/docs/references/messaging/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSms', + description: '/docs/references/messaging/update-sms.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3710,13 +3937,18 @@ App::patch('/v1/messaging/messages/push/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updatePush') - ->label('sdk.description', '/docs/references/messaging/update-push.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updatePush', + description: '/docs/references/messaging/update-push.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3964,13 +4196,19 @@ App::delete('/v1/messaging/messages/:messageId') ->label('event', 'messages.[messageId].delete') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/messaging/delete-message.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'delete', + description: '/docs/references/messaging/delete-message.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') ->inject('dbForPlatform') @@ -4016,4 +4254,4 @@ App::delete('/v1/messaging/messages/:messageId') ->setPayload($response->output($message, Response::MODEL_MESSAGE)); $response->noContent(); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 29e46505f5..670628de62 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -3,10 +3,19 @@ use Appwrite\Event\Event; use Appwrite\Event\Migration; use Appwrite\Extend\Exception; +use Appwrite\Permission; +use Appwrite\Role; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Migrations; +use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; @@ -17,7 +26,9 @@ use Utopia\Migration\Sources\Appwrite; use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; +use Utopia\System\System; use Utopia\Validator\ArrayList; +use Utopia\Validator\Host; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -31,13 +42,18 @@ App::post('/v1/migrations/appwrite') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createAppwriteMigration') - ->label('sdk.description', '/docs/references/migrations/migration-appwrite.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createAppwriteMigration', + description: '/docs/references/migrations/migration-appwrite.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate') ->param('endpoint', '', new URL(), "Source's Appwrite Endpoint") ->param('projectId', '', new UID(), "Source's Project ID") @@ -80,19 +96,25 @@ App::post('/v1/migrations/appwrite') ->dynamic($migration, Response::MODEL_MIGRATION); }); + App::post('/v1/migrations/firebase') ->groups(['api', 'migrations']) ->desc('Migrate Firebase data') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseMigration') - ->label('sdk.description', '/docs/references/migrations/migration-firebase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createFirebaseMigration', + description: '/docs/references/migrations/migration-firebase.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') ->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials') ->inject('response') @@ -147,13 +169,18 @@ App::post('/v1/migrations/supabase') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createSupabaseMigration') - ->label('sdk.description', '/docs/references/migrations/migration-supabase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createSupabaseMigration', + description: '/docs/references/migrations/migration-supabase.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Supabase::getSupportedResources(), true)), 'List of resources to migrate') ->param('endpoint', '', new URL(), 'Source\'s Supabase Endpoint') ->param('apiKey', '', new Text(512), 'Source\'s API Key') @@ -208,13 +235,18 @@ App::post('/v1/migrations/nhost') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createNHostMigration') - ->label('sdk.description', '/docs/references/migrations/migration-nhost.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createNHostMigration', + description: '/docs/references/migrations/migration-nhost.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(NHost::getSupportedResources())), 'List of resources to migrate') ->param('subdomain', '', new Text(512), 'Source\'s Subdomain') ->param('region', '', new Text(512), 'Source\'s Region') @@ -269,13 +301,18 @@ App::get('/v1/migrations') ->groups(['api', 'migrations']) ->desc('List migrations') ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/migrations/list-migrations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_LIST) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'list', + description: '/docs/references/migrations/list-migrations.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_LIST, + ) + ] + )) ->param('queries', [], new Migrations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -328,13 +365,18 @@ App::get('/v1/migrations/:migrationId') ->groups(['api', 'migrations']) ->desc('Get migration') ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/migrations/get-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'get', + description: '/docs/references/migrations/get-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('migrationId', '', new UID(), 'Migration unique ID.') ->inject('response') ->inject('dbForProject') @@ -352,13 +394,18 @@ App::get('/v1/migrations/appwrite/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Appwrite data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getAppwriteReport') - ->label('sdk.description', '/docs/references/migrations/migration-appwrite-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getAppwriteReport', + description: '/docs/references/migrations/migration-appwrite-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate') ->param('endpoint', '', new URL(), "Source's Appwrite Endpoint") ->param('projectID', '', new Text(512), "Source's Project ID") @@ -394,13 +441,18 @@ App::get('/v1/migrations/firebase/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Firebase data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getFirebaseReport') - ->label('sdk.description', '/docs/references/migrations/migration-firebase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getFirebaseReport', + description: '/docs/references/migrations/migration-firebase-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') ->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials') ->inject('response') @@ -441,13 +493,18 @@ App::get('/v1/migrations/supabase/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Supabase Data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getSupabaseReport') - ->label('sdk.description', '/docs/references/migrations/migration-supabase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getSupabaseReport', + description: '/docs/references/migrations/migration-supabase-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Supabase::getSupportedResources(), true)), 'List of resources to migrate') ->param('endpoint', '', new URL(), 'Source\'s Supabase Endpoint.') ->param('apiKey', '', new Text(512), 'Source\'s API Key.') @@ -484,13 +541,18 @@ App::get('/v1/migrations/nhost/report') ->groups(['api', 'migrations']) ->desc('Generate a report on NHost Data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getNHostReport') - ->label('sdk.description', '/docs/references/migrations/migration-nhost-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getNHostReport', + description: '/docs/references/migrations/migration-nhost-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(NHost::getSupportedResources())), 'List of resources to migrate.') ->param('subdomain', '', new Text(512), 'Source\'s Subdomain.') ->param('region', '', new Text(512), 'Source\'s Region.') @@ -530,13 +592,18 @@ App::patch('/v1/migrations/:migrationId') ->label('event', 'migrations.[migrationId].retry') ->label('audits.event', 'migration.retry') ->label('audits.resource', 'migrations/{request.migrationId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'retry') - ->label('sdk.description', '/docs/references/migrations/retry-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'retry', + description: '/docs/references/migrations/retry-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('migrationId', '', new UID(), 'Migration unique ID.') ->inject('response') ->inject('dbForProject') @@ -575,12 +642,19 @@ App::delete('/v1/migrations/:migrationId') ->label('event', 'migrations.[migrationId].delete') ->label('audits.event', 'migrationId.delete') ->label('audits.resource', 'migrations/{request.migrationId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/migrations/delete-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'delete', + description: '/docs/references/migrations/delete-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('migrationId', '', new UID(), 'Migration ID.') ->inject('response') ->inject('dbForProject') @@ -599,4 +673,4 @@ App::delete('/v1/migrations/:migrationId') $queueForEvents->setParam('migrationId', $migration->getId()); $response->noContent(); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 5a1bf063f2..50ef982799 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -1,6 +1,10 @@ <?php use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; @@ -20,12 +24,18 @@ App::get('/v1/project/usage') ->desc('Get project usage stats') ->groups(['api', 'usage']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_PROJECT) + ->label('sdk', new Method( + namespace: 'project', + name: 'getUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_PROJECT, + ) + ] + )) ->param('startDate', '', new DateTimeValidator(), 'Starting date for the usage') ->param('endDate', '', new DateTimeValidator(), 'End date for the usage') ->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true) @@ -357,13 +367,18 @@ App::post('/v1/project/variables') ->groups(['api']) ->label('scope', 'projects.write') ->label('audits.event', 'variable.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'createVariable') - ->label('sdk.description', '/docs/references/project/create-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'createVariable', + description: '/docs/references/project/create-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) ->inject('project') @@ -411,13 +426,18 @@ App::get('/v1/project/variables') ->desc('List variables') ->groups(['api']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'listVariables') - ->label('sdk.description', '/docs/references/project/list-variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE_LIST) + ->label('sdk', new Method( + namespace: 'project', + name: 'listVariables', + description: '/docs/references/project/list-variables.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE_LIST, + ) + ] + )) ->inject('response') ->inject('dbForProject') ->action(function (Response $response, Database $dbForProject) { @@ -436,13 +456,18 @@ App::get('/v1/project/variables/:variableId') ->desc('Get variable') ->groups(['api']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'getVariable') - ->label('sdk.description', '/docs/references/project/get-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'getVariable', + description: '/docs/references/project/get-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('project') @@ -460,13 +485,18 @@ App::put('/v1/project/variables/:variableId') ->desc('Update variable') ->groups(['api']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'updateVariable') - ->label('sdk.description', '/docs/references/project/update-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'updateVariable', + description: '/docs/references/project/update-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) @@ -506,12 +536,19 @@ App::delete('/v1/project/variables/:variableId') ->desc('Delete variable') ->groups(['api']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'deleteVariable') - ->label('sdk.description', '/docs/references/project/delete-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'project', + name: 'deleteVariable', + description: '/docs/references/project/delete-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('project') ->inject('response') @@ -533,4 +570,4 @@ App::delete('/v1/project/variables/:variableId') } $response->noContent(); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index e0b83dcab1..896e708327 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -10,6 +10,10 @@ use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Origin; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\ProjectId; use Appwrite\Utopia\Database\Validator\Queries\Projects; @@ -62,12 +66,18 @@ App::post('/v1/projects') ->label('audits.event', 'projects.create') ->label('audits.resource', 'project/{response.$id}') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'create') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'create', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('teamId', '', new UID(), 'Team unique ID.') @@ -285,12 +295,18 @@ App::get('/v1/projects') ->desc('List projects') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'list') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'list', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT_LIST, + ) + ] + )) ->param('queries', [], new Projects(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -344,12 +360,18 @@ App::get('/v1/projects/:projectId') ->desc('Get project') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'get') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'get', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('dbForPlatform') @@ -370,12 +392,18 @@ App::patch('/v1/projects/:projectId') ->label('scope', 'projects.write') ->label('audits.event', 'projects.update') ->label('audits.resource', 'project/{request.projectId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'update') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'update', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) @@ -417,12 +445,18 @@ App::patch('/v1/projects/:projectId/team') ->desc('Update project team') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateTeam') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateTeam', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('teamId', '', new UID(), 'Team ID of the team to transfer project to.') ->inject('response') @@ -485,12 +519,18 @@ App::patch('/v1/projects/:projectId/service') ->desc('Update service status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateServiceStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateServiceStatus', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') @@ -516,12 +556,18 @@ App::patch('/v1/projects/:projectId/service/all') ->desc('Update all service status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateServiceStatusAll') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateServiceStatusAll', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') @@ -550,12 +596,18 @@ App::patch('/v1/projects/:projectId/api') ->desc('Update API status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateApiStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateApiStatus', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('api', '', new WhiteList(array_keys(Config::getParam('apis')), true), 'API name.') ->param('status', null, new Boolean(), 'API status.') @@ -581,12 +633,18 @@ App::patch('/v1/projects/:projectId/api/all') ->desc('Update all API status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateApiStatusAll') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateApiStatusAll', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'API status.') ->inject('response') @@ -615,12 +673,18 @@ App::patch('/v1/projects/:projectId/oauth2') ->desc('Update project OAuth2') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateOAuth2') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateOAuth2', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'Provider Name') ->param('appId', null, new Text(256), 'Provider app ID. Max length: 256 chars.', true) @@ -659,12 +723,18 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') ->desc('Update project sessions emails') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSessionAlerts') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSessionAlerts', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.') ->inject('response') @@ -690,12 +760,18 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') ->desc('Update project memberships privacy attributes') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateMembershipsPrivacy') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateMembershipsPrivacy', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('userName', true, new Boolean(true), 'Set to true to show userName to members of a team.') ->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.') @@ -725,12 +801,18 @@ App::patch('/v1/projects/:projectId/auth/limit') ->desc('Update project users limit') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthLimit') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthLimit', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.') ->inject('response') @@ -756,12 +838,18 @@ App::patch('/v1/projects/:projectId/auth/duration') ->desc('Update project authentication duration') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthDuration') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthDuration', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.') ->inject('response') @@ -787,12 +875,18 @@ App::patch('/v1/projects/:projectId/auth/:method') ->desc('Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthStatus', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false) ->param('status', false, new Boolean(true), 'Set the status of this auth method.') @@ -821,12 +915,18 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->desc('Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthPasswordHistory') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthPasswordHistory', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0') ->inject('response') @@ -852,12 +952,18 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->desc('Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthPasswordDictionary') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthPasswordDictionary', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.') ->inject('response') @@ -883,12 +989,18 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->desc('Enable or disable checking user passwords for similarity with their personal data.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updatePersonalDataCheck') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updatePersonalDataCheck', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.') ->inject('response') @@ -914,12 +1026,18 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->desc('Update project user sessions limit') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthSessionsLimit') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthSessionsLimit', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT) ->inject('response') @@ -945,12 +1063,18 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') ->desc('Update the mock numbers for the project') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateMockNumbers') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateMockNumbers', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('numbers', '', new ArrayList(new MockNumber(), 10), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.') ->inject('response') @@ -986,11 +1110,19 @@ App::delete('/v1/projects/:projectId') ->label('audits.event', 'projects.delete') ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'delete') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'delete', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('user') @@ -1021,12 +1153,18 @@ App::post('/v1/projects/:projectId/webhooks') ->desc('Create webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createWebhook', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) @@ -1079,12 +1217,18 @@ App::get('/v1/projects/:projectId/webhooks') ->desc('List webhooks') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listWebhooks') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listWebhooks', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('dbForPlatform') @@ -1111,12 +1255,18 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Get webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getWebhook', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') @@ -1145,12 +1295,18 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Update webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateWebhook', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') @@ -1204,12 +1360,18 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->desc('Update webhook signature key') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateWebhookSignature') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateWebhookSignature', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') @@ -1243,11 +1405,19 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Delete webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteWebhook', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') @@ -1282,12 +1452,18 @@ App::post('/v1/projects/:projectId/keys') ->desc('Create key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createKey') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createKey', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') @@ -1332,12 +1508,18 @@ App::get('/v1/projects/:projectId/keys') ->desc('List keys') ->groups(['api', 'projects']) ->label('scope', 'keys.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listKeys') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listKeys', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('dbForPlatform') @@ -1364,12 +1546,18 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->desc('Get key') ->groups(['api', 'projects']) ->label('scope', 'keys.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getKey') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getKey', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') @@ -1398,12 +1586,18 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->desc('Update key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateKey') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateKey', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') @@ -1444,11 +1638,19 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->desc('Delete key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteKey') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteKey', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') @@ -1483,12 +1685,18 @@ App::post('/v1/projects/:projectId/jwts') ->groups(['api', 'projects']) ->desc('Create JWT') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createJWT') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createJWT', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) @@ -1520,12 +1728,18 @@ App::post('/v1/projects/:projectId/platforms') ->label('audits.event', 'platforms.create') ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createPlatform') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createPlatform', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY, Origin::CLIENT_TYPE_REACT_NATIVE_IOS, Origin::CLIENT_TYPE_REACT_NATIVE_ANDROID], true), 'Platform type.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') @@ -1570,12 +1784,18 @@ App::get('/v1/projects/:projectId/platforms') ->desc('List platforms') ->groups(['api', 'projects']) ->label('scope', 'platforms.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listPlatforms') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listPlatforms', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('dbForPlatform') @@ -1602,12 +1822,18 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->desc('Get platform') ->groups(['api', 'projects']) ->label('scope', 'platforms.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getPlatform') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getPlatform', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') @@ -1636,12 +1862,18 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->desc('Update platform') ->groups(['api', 'projects']) ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updatePlatform') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updatePlatform', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') @@ -1685,11 +1917,19 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->label('audits.event', 'platforms.delete') ->label('audits.resource', 'project/{request.projectId}/platform/${request.platformId}') ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deletePlatform') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deletePlatform', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') @@ -1724,12 +1964,18 @@ App::patch('/v1/projects/:projectId/smtp') ->desc('Update SMTP') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSmtp') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSmtp', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(), 'Enable custom SMTP service') ->param('senderName', '', new Text(255, 0), 'Name of the email sender', true) @@ -1814,11 +2060,18 @@ App::post('/v1/projects/:projectId/smtp/tests') ->desc('Create SMTP test') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createSmtpTest') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createSmtpTest', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('emails', [], new ArrayList(new Email(), 10), 'Array of emails to send test email to. Maximum of 10 emails are allowed.') ->param('senderName', System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'), new Text(255, 0), 'Name of the email sender') @@ -1873,12 +2126,18 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Get custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getSmsTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -1914,12 +2173,18 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Get custom email template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getEmailTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -1966,12 +2231,18 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Update custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSmsTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -2006,12 +2277,18 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Update custom email templates') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateEmailTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -2056,12 +2333,19 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Reset custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteSmsTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ], + contentType: ContentType::JSON + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -2099,12 +2383,19 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Reset custom email template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteEmailTemplate', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ], + contentType: ContentType::JSON + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -2138,4 +2429,4 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') 'replyTo' => $template['replyTo'], 'message' => $template['message'] ]), Response::MODEL_EMAIL_TEMPLATE); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 0d2fed8e66..ef39ed0ab6 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -5,6 +5,10 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\CNAME; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Rules; use Appwrite\Utopia\Response; use Utopia\App; @@ -29,13 +33,18 @@ App::post('/v1/proxy/rules') ->label('event', 'rules.[ruleId].create') ->label('audits.event', 'rule.create') ->label('audits.resource', 'rule/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'createRule') - ->label('sdk.description', '/docs/references/proxy/create-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'createRule', + description: '/docs/references/proxy/create-rule.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) ->param('domain', null, new ValidatorDomain(), 'Domain name.') ->param('resourceType', null, new WhiteList(['api', 'function']), 'Action definition for the rule. Possible values are "api", "function"') ->param('resourceId', '', new UID(), 'ID of resource for the action type. If resourceType is "api", leave empty. If resourceType is "function", provide ID of the function.', true) @@ -160,13 +169,18 @@ App::get('/v1/proxy/rules') ->groups(['api', 'proxy']) ->desc('List rules') ->label('scope', 'rules.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'listRules') - ->label('sdk.description', '/docs/references/proxy/list-rules.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE_LIST) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'listRules', + description: '/docs/references/proxy/list-rules.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE_LIST, + ) + ] + )) ->param('queries', [], new Rules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -229,13 +243,18 @@ App::get('/v1/proxy/rules/:ruleId') ->groups(['api', 'proxy']) ->desc('Get rule') ->label('scope', 'rules.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'getRule') - ->label('sdk.description', '/docs/references/proxy/get-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'getRule', + description: '/docs/references/proxy/get-rule.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') @@ -261,12 +280,19 @@ App::delete('/v1/proxy/rules/:ruleId') ->label('event', 'rules.[ruleId].delete') ->label('audits.event', 'rules.delete') ->label('audits.resource', 'rule/{request.ruleId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'deleteRule') - ->label('sdk.description', '/docs/references/proxy/delete-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'deleteRule', + description: '/docs/references/proxy/delete-rule.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') @@ -298,12 +324,18 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->label('event', 'rules.[ruleId].update') ->label('audits.event', 'rule.update') ->label('audits.resource', 'rule/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'updateRuleVerification') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'updateRuleVerification', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('queueForCertificates') diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index e92b55f140..8ed7aaff22 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -9,6 +9,11 @@ use Appwrite\Event\Event; use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Buckets; use Appwrite\Utopia\Database\Validator\Queries\Files; @@ -55,13 +60,18 @@ App::post('/v1/storage/buckets') ->label('event', 'buckets.[bucketId].create') ->label('audits.event', 'bucket.create') ->label('audits.resource', 'bucket/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'createBucket') - ->label('sdk.description', '/docs/references/storage/create-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'createBucket', + description: '/docs/references/storage/create-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Bucket name') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) @@ -152,13 +162,18 @@ App::get('/v1/storage/buckets') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'listBuckets') - ->label('sdk.description', '/docs/references/storage/list-buckets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) + ->label('sdk', new Method( + namespace: 'storage', + name: 'listBuckets', + description: '/docs/references/storage/list-buckets.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET_LIST, + ) + ] + )) ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -213,13 +228,18 @@ App::get('/v1/storage/buckets/:bucketId') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getBucket') - ->label('sdk.description', '/docs/references/storage/get-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getBucket', + description: '/docs/references/storage/get-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->inject('response') ->inject('dbForProject') @@ -242,13 +262,18 @@ App::put('/v1/storage/buckets/:bucketId') ->label('event', 'buckets.[bucketId].update') ->label('audits.event', 'bucket.update') ->label('audits.resource', 'bucket/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'updateBucket') - ->label('sdk.description', '/docs/references/storage/update-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'updateBucket', + description: '/docs/references/storage/update-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->param('name', null, new Text(128), 'Bucket name', false) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) @@ -307,12 +332,19 @@ App::delete('/v1/storage/buckets/:bucketId') ->label('audits.event', 'bucket.delete') ->label('event', 'buckets.[bucketId].delete') ->label('audits.resource', 'bucket/{request.bucketId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'deleteBucket') - ->label('sdk.description', '/docs/references/storage/delete-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'deleteBucket', + description: '/docs/references/storage/delete-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->inject('response') ->inject('dbForProject') @@ -353,15 +385,20 @@ App::post('/v1/storage/buckets/:bucketId/files') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'createFile') - ->label('sdk.description', '/docs/references/storage/create-file.md') - ->label('sdk.request.type', 'multipart/form-data') - ->label('sdk.methodType', 'upload') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'createFile', + description: '/docs/references/storage/create-file.md', + type: MethodType::UPLOAD, + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + requestType: 'multipart/form-data', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new CustomId(), 'File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('file', [], new File(), 'Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https://appwrite.io/docs/products/storage/upload-download#input-file).', skipValidation: true) @@ -717,13 +754,18 @@ App::get('/v1/storage/buckets/:bucketId/files') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'listFiles') - ->label('sdk.description', '/docs/references/storage/list-files.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE_LIST) + ->label('sdk', new Method( + namespace: 'storage', + name: 'listFiles', + description: '/docs/references/storage/list-files.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE_LIST, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -809,13 +851,18 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFile') - ->label('sdk.description', '/docs/references/storage/get-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFile', + description: '/docs/references/storage/get-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -860,13 +907,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->label('cache', true) ->label('cache.resourceType', 'bucket/{request.bucketId}') ->label('cache.resource', 'file/{request.fileId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFilePreview') - ->label('sdk.description', '/docs/references/storage/get-file-preview.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFilePreview', + description: '/docs/references/storage/get-file-preview.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::IMAGE + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID') ->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true) @@ -1036,13 +1090,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFileDownload') - ->label('sdk.description', '/docs/references/storage/get-file-download.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFileDownload', + description: '/docs/references/storage/get-file-download.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::ANY, + )) ->param('bucketId', '', new UID(), 'Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('request') @@ -1177,13 +1238,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFileView') - ->label('sdk.description', '/docs/references/storage/get-file-view.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFileView', + description: '/docs/references/storage/get-file-view.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::ANY, + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -1490,13 +1558,18 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'updateFile') - ->label('sdk.description', '/docs/references/storage/update-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'updateFile', + description: '/docs/references/storage/update-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('name', null, new Text(255), 'Name of the file', true) @@ -1599,12 +1672,19 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'deleteFile') - ->label('sdk.description', '/docs/references/storage/delete-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'deleteFile', + description: '/docs/references/storage/delete-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -1691,12 +1771,18 @@ App::get('/v1/storage/usage') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_STORAGE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_STORAGE, + ) + ] + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') @@ -1771,12 +1857,18 @@ App::get('/v1/storage/:bucketId/usage') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getBucketUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_BUCKETS) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getBucketUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_BUCKETS, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') @@ -1850,4 +1942,4 @@ App::get('/v1/storage/:bucketId/usage') 'files' => $usage[$metrics[0]]['data'], 'storage' => $usage[$metrics[1]]['data'], ]), Response::MODEL_USAGE_BUCKETS); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 461e90da58..612df0d439 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -12,6 +12,10 @@ use Appwrite\Event\Usage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Platform\Workers\Deletes; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Memberships; @@ -56,13 +60,18 @@ App::post('/v1/teams') ->label('scope', 'teams.write') ->label('audits.event', 'team.create') ->label('audits.resource', 'team/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/teams/create-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) + ->label('sdk', new Method( + namespace: 'teams', + name: 'create', + description: '/docs/references/teams/create-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true) @@ -141,14 +150,18 @@ App::get('/v1/teams') ->desc('List teams') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/teams/list-teams.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM_LIST) - ->label('sdk.offline.model', '/teams') + ->label('sdk', new Method( + namespace: 'teams', + name: 'list', + description: '/docs/references/teams/list-teams.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM_LIST, + ) + ] + )) ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -205,15 +218,18 @@ App::get('/v1/teams/:teamId') ->desc('Get team') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/teams/get-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) - ->label('sdk.offline.model', '/teams') - ->label('sdk.offline.key', '{teamId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'get', + description: '/docs/references/teams/get-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('dbForProject') @@ -232,14 +248,18 @@ App::get('/v1/teams/:teamId/prefs') ->desc('Get team preferences') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/teams/get-team-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/teams/{teamId}/prefs') + ->label('sdk', new Method( + namespace: 'teams', + name: 'getPrefs', + description: '/docs/references/teams/get-team-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('dbForProject') @@ -263,15 +283,18 @@ App::put('/v1/teams/:teamId') ->label('scope', 'teams.write') ->label('audits.event', 'team.update') ->label('audits.resource', 'team/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/teams/update-team-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) - ->label('sdk.offline.model', '/teams') - ->label('sdk.offline.key', '{teamId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateName', + description: '/docs/references/teams/update-team-name.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('name', null, new Text(128), 'New team name. Max length: 128 chars.') ->inject('requestTimestamp') @@ -307,14 +330,18 @@ App::put('/v1/teams/:teamId/prefs') ->label('audits.event', 'team.update') ->label('audits.resource', 'team/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/teams/update-team-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/teams/{teamId}/prefs') + ->label('sdk', new Method( + namespace: 'teams', + name: 'updatePrefs', + description: '/docs/references/teams/update-team-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.') ->inject('response') @@ -342,12 +369,19 @@ App::delete('/v1/teams/:teamId') ->label('scope', 'teams.write') ->label('audits.event', 'team.delete') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/teams/delete-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'teams', + name: 'delete', + description: '/docs/references/teams/delete-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('getProjectDB') @@ -393,13 +427,18 @@ App::post('/v1/teams/:teamId/memberships') ->label('audits.event', 'membership.create') ->label('audits.resource', 'team/{request.teamId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'createMembership') - ->label('sdk.description', '/docs/references/teams/create-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'createMembership', + description: '/docs/references/teams/create-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->label('abuse-limit', 10) ->param('teamId', '', new UID(), 'Team ID.') ->param('email', '', new Email(), 'Email of the new team member.', true) @@ -742,14 +781,18 @@ App::get('/v1/teams/:teamId/memberships') ->desc('List team memberships') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'listMemberships') - ->label('sdk.description', '/docs/references/teams/list-team-members.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) - ->label('sdk.offline.model', '/teams/{teamId}/memberships') + ->label('sdk', new Method( + namespace: 'teams', + name: 'listMemberships', + description: '/docs/references/teams/list-team-members.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP_LIST, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -876,15 +919,18 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->desc('Get team membership') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'getMembership') - ->label('sdk.description', '/docs/references/teams/get-team-member.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) - ->label('sdk.offline.model', '/teams/{teamId}/memberships') - ->label('sdk.offline.key', '{membershipId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'getMembership', + description: '/docs/references/teams/get-team-member.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->inject('response') @@ -959,13 +1005,18 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->label('scope', 'teams.write') ->label('audits.event', 'membership.update') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateMembership') - ->label('sdk.description', '/docs/references/teams/update-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateMembership', + description: '/docs/references/teams/update-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->param('roles', [], function (Document $project) { @@ -1042,13 +1093,18 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->label('audits.event', 'membership.update') ->label('audits.resource', 'team/{request.teamId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateMembershipStatus') - ->label('sdk.description', '/docs/references/teams/update-team-membership-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateMembershipStatus', + description: '/docs/references/teams/update-team-membership-status.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->param('userId', '', new UID(), 'User ID.') @@ -1194,12 +1250,19 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->label('scope', 'teams.write') ->label('audits.event', 'membership.delete') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'deleteMembership') - ->label('sdk.description', '/docs/references/teams/delete-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'teams', + name: 'deleteMembership', + description: '/docs/references/teams/delete-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->inject('response') @@ -1257,13 +1320,18 @@ App::get('/v1/teams/:teamId/logs') ->desc('List team logs') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/teams/get-team-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'teams', + name: 'listLogs', + description: '/docs/references/teams/get-team-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -1340,4 +1408,4 @@ App::get('/v1/teams/:teamId/logs') 'total' => $audit->countLogsByResource($resource), 'logs' => $output, ]), Response::MODEL_LOG_LIST); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 9fe7f433c9..9c3026793b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -15,6 +15,10 @@ use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Database\Validator\Queries\Targets; @@ -185,13 +189,18 @@ App::post('/v1/users') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/users/create-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'create', + description: '/docs/references/users/create-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', null, new Email(), 'User email.', true) ->param('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -214,13 +223,18 @@ App::post('/v1/users/bcrypt') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createBcryptUser') - ->label('sdk.description', '/docs/references/users/create-bcrypt-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createBcryptUser', + description: '/docs/references/users/create-bcrypt-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Bcrypt.') @@ -243,13 +257,18 @@ App::post('/v1/users/md5') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createMD5User') - ->label('sdk.description', '/docs/references/users/create-md5-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createMD5User', + description: '/docs/references/users/create-md5-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using MD5.') @@ -272,13 +291,18 @@ App::post('/v1/users/argon2') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createArgon2User') - ->label('sdk.description', '/docs/references/users/create-argon2-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createArgon2User', + description: '/docs/references/users/create-argon2-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Argon2.') @@ -301,13 +325,18 @@ App::post('/v1/users/sha') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createSHAUser') - ->label('sdk.description', '/docs/references/users/create-sha-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createSHAUser', + description: '/docs/references/users/create-sha-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using SHA.') @@ -337,13 +366,18 @@ App::post('/v1/users/phpass') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createPHPassUser') - ->label('sdk.description', '/docs/references/users/create-phpass-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createPHPassUser', + description: '/docs/references/users/create-phpass-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using PHPass.') @@ -366,13 +400,18 @@ App::post('/v1/users/scrypt') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createScryptUser') - ->label('sdk.description', '/docs/references/users/create-scrypt-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createScryptUser', + description: '/docs/references/users/create-scrypt-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Scrypt.') @@ -408,13 +447,18 @@ App::post('/v1/users/scrypt-modified') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createScryptModifiedUser') - ->label('sdk.description', '/docs/references/users/create-scrypt-modified-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createScryptModifiedUser', + description: '/docs/references/users/create-scrypt-modified-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Scrypt Modified.') @@ -441,13 +485,18 @@ App::post('/v1/users/:userId/targets') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].create') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createTarget') - ->label('sdk.description', '/docs/references/users/create-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'createTarget', + description: '/docs/references/users/create-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('userId', '', new UID(), 'User ID.') ->param('providerType', '', new WhiteList([MESSAGE_TYPE_EMAIL, MESSAGE_TYPE_SMS, MESSAGE_TYPE_PUSH]), 'The target provider type. Can be one of the following: `email`, `sms` or `push`.') @@ -527,13 +576,18 @@ App::get('/v1/users') ->desc('List users') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/users/list-users.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'list', + description: '/docs/references/users/list-users.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER_LIST, + ) + ] + )) ->param('queries', [], new Users(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Users::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -587,13 +641,18 @@ App::get('/v1/users/:userId') ->desc('Get user') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/users/get-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'get', + description: '/docs/references/users/get-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -612,13 +671,18 @@ App::get('/v1/users/:userId/prefs') ->desc('Get user preferences') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/users/get-user-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) + ->label('sdk', new Method( + namespace: 'users', + name: 'getPrefs', + description: '/docs/references/users/get-user-prefs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -639,13 +703,18 @@ App::get('/v1/users/:userId/targets/:targetId') ->desc('Get user target') ->groups(['api', 'users']) ->label('scope', 'targets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getTarget') - ->label('sdk.description', '/docs/references/users/get-user-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'getTarget', + description: '/docs/references/users/get-user-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->inject('response') @@ -671,13 +740,18 @@ App::get('/v1/users/:userId/sessions') ->desc('List user sessions') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listSessions') - ->label('sdk.description', '/docs/references/users/list-user-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listSessions', + description: '/docs/references/users/list-user-sessions.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -712,13 +786,18 @@ App::get('/v1/users/:userId/memberships') ->desc('List user memberships') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listMemberships') - ->label('sdk.description', '/docs/references/users/list-user-memberships.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listMemberships', + description: '/docs/references/users/list-user-memberships.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -751,13 +830,18 @@ App::get('/v1/users/:userId/logs') ->desc('List user logs') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/users/list-user-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listLogs', + description: '/docs/references/users/list-user-logs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') @@ -840,13 +924,18 @@ App::get('/v1/users/:userId/targets') ->desc('List user targets') ->groups(['api', 'users']) ->label('scope', 'targets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listTargets') - ->label('sdk.description', '/docs/references/users/list-user-targets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listTargets', + description: '/docs/references/users/list-user-targets.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Users::ALLOWED_ATTRIBUTES), true) ->inject('response') @@ -900,13 +989,18 @@ App::get('/v1/users/identities') ->desc('List identities') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listIdentities') - ->label('sdk.description', '/docs/references/users/list-identities.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listIdentities', + description: '/docs/references/users/list-identities.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_IDENTITY_LIST, + ) + ] + )) ->param('queries', [], new Identities(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -964,13 +1058,18 @@ App::patch('/v1/users/:userId/status') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateStatus') - ->label('sdk.description', '/docs/references/users/update-user-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateStatus', + description: '/docs/references/users/update-user-status.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('status', null, new Boolean(true), 'User Status. To activate the user pass `true` and to block the user pass `false`.') ->inject('response') @@ -999,13 +1098,18 @@ App::put('/v1/users/:userId/labels') ->label('scope', 'users.write') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateLabels') - ->label('sdk.description', '/docs/references/users/update-user-labels.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateLabels', + description: '/docs/references/users/update-user-labels.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_LABELS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_LABELS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.') ->inject('response') @@ -1036,13 +1140,18 @@ App::patch('/v1/users/:userId/verification/phone') ->label('scope', 'users.write') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePhoneVerification') - ->label('sdk.description', '/docs/references/users/update-user-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePhoneVerification', + description: '/docs/references/users/update-user-phone-verification.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('phoneVerification', false, new Boolean(), 'User phone verification status.') ->inject('response') @@ -1072,13 +1181,18 @@ App::patch('/v1/users/:userId/name') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/users/update-user-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateName', + description: '/docs/references/users/update-user-name.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('name', '', new Text(128, 0), 'User name. Max length: 128 chars.') ->inject('response') @@ -1109,13 +1223,18 @@ App::patch('/v1/users/:userId/password') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePassword') - ->label('sdk.description', '/docs/references/users/update-user-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePassword', + description: '/docs/references/users/update-user-password.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, enabled: $project->getAttribute('auths', [])['passwordDictionary'] ?? false, allowEmpty: true), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary']) ->inject('response') @@ -1186,13 +1305,18 @@ App::patch('/v1/users/:userId/email') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/users/update-user-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateEmail', + description: '/docs/references/users/update-user-email.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('email', '', new Email(allowEmpty: true), 'User email.') ->inject('response') @@ -1280,13 +1404,18 @@ App::patch('/v1/users/:userId/phone') ->label('scope', 'users.write') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePhone') - ->label('sdk.description', '/docs/references/users/update-user-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePhone', + description: '/docs/references/users/update-user-phone.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('number', '', new Phone(allowEmpty: true), 'User phone number.') ->inject('response') @@ -1364,13 +1493,18 @@ App::patch('/v1/users/:userId/verification') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{request.userId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateEmailVerification') - ->label('sdk.description', '/docs/references/users/update-user-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateEmailVerification', + description: '/docs/references/users/update-user-email-verification.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('emailVerification', false, new Boolean(), 'User email verification status.') ->inject('response') @@ -1396,13 +1530,18 @@ App::patch('/v1/users/:userId/prefs') ->groups(['api', 'users']) ->label('event', 'users.[userId].update.prefs') ->label('scope', 'users.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/users/update-user-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePrefs', + description: '/docs/references/users/update-user-prefs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.') ->inject('response') @@ -1431,13 +1570,18 @@ App::patch('/v1/users/:userId/targets/:targetId') ->label('audits.resource', 'target/{response.$id}') ->label('event', 'users.[userId].targets.[targetId].update') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateTarget') - ->label('sdk.description', '/docs/references/users/update-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateTarget', + description: '/docs/references/users/update-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) @@ -1530,13 +1674,18 @@ App::patch('/v1/users/:userId/mfa') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateMfa') - ->label('sdk.description', '/docs/references/users/update-user-mfa.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateMfa', + description: '/docs/references/users/update-user-mfa.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('mfa', null, new Boolean(), 'Enable or disable MFA.') ->inject('response') @@ -1564,13 +1713,18 @@ App::get('/v1/users/:userId/mfa/factors') ->groups(['api', 'users']) ->label('scope', 'users.read') ->label('usage.metric', 'users.{scope}.requests.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listMfaFactors') - ->label('sdk.description', '/docs/references/users/list-mfa-factors.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_FACTORS) + ->label('sdk', new Method( + namespace: 'users', + name: 'listMfaFactors', + description: '/docs/references/users/list-mfa-factors.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_FACTORS, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1597,13 +1751,18 @@ App::get('/v1/users/:userId/mfa/recovery-codes') ->groups(['api', 'users']) ->label('scope', 'users.read') ->label('usage.metric', 'users.{scope}.requests.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/get-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'getMfaRecoveryCodes', + description: '/docs/references/users/get-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1636,13 +1795,18 @@ App::patch('/v1/users/:userId/mfa/recovery-codes') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/create-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'createMfaRecoveryCodes', + description: '/docs/references/users/create-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1682,13 +1846,18 @@ App::put('/v1/users/:userId/mfa/recovery-codes') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/update-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateMfaRecoveryCodes', + description: '/docs/references/users/update-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1727,13 +1896,19 @@ App::delete('/v1/users/:userId/mfa/authenticators/:type') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteMfaAuthenticator') - ->label('sdk.description', '/docs/references/users/delete-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteMfaAuthenticator', + description: '/docs/references/users/delete-mfa-authenticator.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->inject('response') @@ -1768,13 +1943,18 @@ App::post('/v1/users/:userId/sessions') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{request.userId}') ->label('usage.metric', 'sessions.{scope}.requests.create') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createSession') - ->label('sdk.description', '/docs/references/users/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'users', + name: 'createSession', + description: '/docs/references/users/create-session.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ] + )) ->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->inject('request') ->inject('response') @@ -1847,13 +2027,18 @@ App::post('/v1/users/:userId/tokens') ->label('scope', 'users.write') ->label('audits.event', 'tokens.create') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createToken') - ->label('sdk.description', '/docs/references/users/create-token.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'users', + name: 'createToken', + description: '/docs/references/users/create-token.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('length', 6, new Range(4, 128), 'Token length in characters. The default length is 6 characters', true) ->param('expire', Auth::TOKEN_EXPIRATION_GENERIC, new Range(60, Auth::TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true) @@ -1904,12 +2089,19 @@ App::delete('/v1/users/:userId/sessions/:sessionId') ->label('scope', 'users.write') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteSession') - ->label('sdk.description', '/docs/references/users/delete-user-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteSession', + description: '/docs/references/users/delete-user-session.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('sessionId', '', new UID(), 'Session ID.') ->inject('response') @@ -1947,12 +2139,19 @@ App::delete('/v1/users/:userId/sessions') ->label('scope', 'users.write') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteSessions') - ->label('sdk.description', '/docs/references/users/delete-user-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteSessions', + description: '/docs/references/users/delete-user-sessions.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1989,12 +2188,19 @@ App::delete('/v1/users/:userId') ->label('scope', 'users.write') ->label('audits.event', 'user.delete') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/users/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'delete', + description: '/docs/references/users/delete.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -2031,13 +2237,19 @@ App::delete('/v1/users/:userId/targets/:targetId') ->label('audits.resource', 'target/{request.$targetId}') ->label('event', 'users.[userId].targets.[targetId].delete') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteTarget') - ->label('sdk.description', '/docs/references/users/delete-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteTarget', + description: '/docs/references/users/delete-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->inject('queueForEvents') @@ -2082,12 +2294,19 @@ App::delete('/v1/users/identities/:identityId') ->label('scope', 'users.write') ->label('audits.event', 'identity.delete') ->label('audits.resource', 'identity/{request.$identityId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteIdentity') - ->label('sdk.description', '/docs/references/users/delete-identity.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteIdentity', + description: '/docs/references/users/delete-identity.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE, + )) ->param('identityId', '', new UID(), 'Identity ID.') ->inject('response') ->inject('dbForProject') @@ -2114,13 +2333,18 @@ App::post('/v1/users/:userId/jwts') ->desc('Create user JWT') ->groups(['api', 'users']) ->label('scope', 'users.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createJWT') - ->label('sdk.description', '/docs/references/users/create-user-jwt.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'users', + name: 'createJWT', + description: '/docs/references/users/create-user-jwt.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('sessionId', '', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true) ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) @@ -2164,12 +2388,18 @@ App::get('/v1/users/usage') ->desc('Get users usage stats') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_USERS) + ->label('sdk', new Method( + namespace: 'users', + name: 'getUsage', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_USERS, + ) + ] + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') @@ -2235,4 +2465,4 @@ App::get('/v1/users/usage') 'users' => $usage[$metrics[0]]['data'], 'sessions' => $usage[$metrics[1]]['data'], ]), Response::MODEL_USAGE_USERS); - }); + }); \ No newline at end of file diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index f24a0d97fe..e64a2f895b 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -4,6 +4,11 @@ use Appwrite\Auth\OAuth2\Github as OAuth2Github; use Appwrite\Event\Build; use Appwrite\Event\Delete; use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Installations; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; @@ -269,13 +274,21 @@ App::get('/v1/vcs/github/authorize') ->label('scope', 'vcs.read') ->label('sdk.namespace', 'vcs') ->label('error', __DIR__ . '/../../views/general/error.phtml') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createGitHubInstallation') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') - ->label('sdk.hide', true) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createGitHubInstallation', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + type: MethodType::WEBAUTH, + hide: true, + )) ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a successful installation attempt.', true, ['clients']) ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a failed installation attempt.', true, ['clients']) ->inject('request') @@ -442,13 +455,18 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('Get files and directories of a VCS repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getRepositoryContents') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VCS_CONTENT_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getRepositoryContents', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VCS_CONTENT_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->param('providerRootDirectory', '', new Text(256, 0), 'Path to get contents of nested directory', true) @@ -503,13 +521,18 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr ->desc('Detect runtime settings from source code') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createRepositoryDetection') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DETECTION) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createRepositoryDetection', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DETECTION, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->param('providerRootDirectory', '', new Text(256, 0), 'Path to Root Directory', true) @@ -575,13 +598,18 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->desc('List repositories') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listRepositories') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listRepositories', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('gitHub') @@ -670,13 +698,18 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->desc('Create repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createRepository') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createRepository', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('name', '', new Text(256), 'Repository name (slug)') ->param('private', '', new Boolean(false), 'Mark repository public or private') @@ -777,13 +810,18 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('Get repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getRepository') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getRepository', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->inject('gitHub') @@ -826,13 +864,18 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('List repository branches') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listRepositoryBranches') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BRANCH_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listRepositoryBranches', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BRANCH_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->inject('gitHub') @@ -1014,13 +1057,18 @@ App::get('/v1/vcs/installations') ->desc('List installations') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listInstallations') - ->label('sdk.description', '/docs/references/vcs/list-installations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INSTALLATION_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listInstallations', + description: '/docs/references/vcs/list-installations.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INSTALLATION_LIST, + ) + ] + )) ->param('queries', [], new Installations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -1080,13 +1128,18 @@ App::get('/v1/vcs/installations/:installationId') ->desc('Get installation') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getInstallation') - ->label('sdk.description', '/docs/references/vcs/get-installation.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INSTALLATION) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getInstallation', + description: '/docs/references/vcs/get-installation.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INSTALLATION, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') @@ -1109,12 +1162,19 @@ App::delete('/v1/vcs/installations/:installationId') ->desc('Delete installation') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'deleteInstallation') - ->label('sdk.description', '/docs/references/vcs/delete-installation.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'deleteInstallation', + description: '/docs/references/vcs/delete-installation.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') @@ -1142,12 +1202,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->desc('Authorize external deployment') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'updateExternalDeployments') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'updateExternalDeployments', + description: '', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('repositoryId', '', new Text(256), 'VCS Repository Id') ->param('providerPullRequestId', '', new Text(256), 'GitHub Pull Request Id') diff --git a/app/controllers/general.php b/app/controllers/general.php index 6f8566f69b..f6a584b69e 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -10,6 +10,10 @@ use Appwrite\Event\Func; use Appwrite\Event\Usage; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Network\Validator\Origin; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Request; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; use Appwrite\Utopia\Request\Filters\V17 as RequestV17; @@ -116,8 +120,29 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $type = $route->getAttribute('resourceType'); if ($type === 'function') { - $utopia->getRoute()?->label('sdk.namespace', 'functions'); - $utopia->getRoute()?->label('sdk.method', 'createExecution'); + $method = $utopia->getRoute()?->getLabel('sdk', null); + + if (empty($method)) { + $utopia->getRoute()?->label('sdk', new Method( + namespace: 'functions', + name: 'createExecution', + description: '/docs/references/functions/create-execution.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_EXECUTION, + ) + ], + contentType: ContentType::MULTIPART, + requestType: 'application/json', + )); + } else { + /** @var Method $method */ + $method->setNamespace('functions'); + $method->setMethodName('createExecution'); + $utopia->getRoute()?->label('sdk', $method); + } if (System::getEnv('_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS if ($request->getProtocol() !== 'https') { @@ -1146,3 +1171,8 @@ App::wildcard() foreach (Config::getParam('services', []) as $service) { include_once $service['controller']; } + +// Check for any errors found while we were initialising the SDK Methods. +if (!empty(Method::getErrors())) { + throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors())); +} \ No newline at end of file diff --git a/app/controllers/mock.php b/app/controllers/mock.php index afbb176b7e..16d8e03841 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -24,7 +24,7 @@ App::get('/v1/mock/tests/general/oauth2') ->groups(['mock']) ->label('scope', 'public') ->label('docs', false) - ->label('sdk.mock', true) + ->label('mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.') // Important to deny an open redirect attack ->param('scope', '', new Text(100), 'OAuth2 scope list.') @@ -40,7 +40,7 @@ App::get('/v1/mock/tests/general/oauth2/token') ->groups(['mock']) ->label('scope', 'public') ->label('docs', false) - ->label('sdk.mock', true) + ->label('mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') ->param('client_secret', '', new Text(100), 'OAuth2 scope list.') ->param('grant_type', 'authorization_code', new WhiteList(['refresh_token', 'authorization_code']), 'OAuth2 Grant Type.', true) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 182151a6c3..09e49d6100 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -363,11 +363,20 @@ App::init() } /** Do not allow access to disabled services */ - $service = $route->getLabel('sdk.namespace', ''); - if (!empty($service)) { + /** + * @var ?\Appwrite\SDK\Method $method + */ + $method = $route->getLabel('sdk', false); + + if (is_array($method)) { + $method = $method[0]; + } + + if (!empty($method)) { + $namespace = $method->getNamespace(); if ( - array_key_exists($service, $project->getAttribute('services', [])) - && !$project->getAttribute('services', [])[$service] + array_key_exists($namespace, $project->getAttribute('services', [])) + && !$project->getAttribute('services', [])[$namespace] && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); diff --git a/composer.lock b/composer.lock index 68dbc191bf..980dcdcd29 100644 --- a/composer.lock +++ b/composer.lock @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-30T11:49:49+00:00" + "time": "2025-01-15T23:07:07+00:00" }, { "name": "open-telemetry/sdk", @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -3678,16 +3678,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.15", + "version": "0.33.16", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", + "url": "https://api.github.com/repos/utopia-php/http/zipball/e91d4c560d1b809e25faa63d564fef034363b50f", + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f", "shasum": "" }, "require": { @@ -3719,9 +3719,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.15" + "source": "https://github.com/utopia-php/http/tree/0.33.16" }, - "time": "2024-12-10T13:07:04+00:00" + "time": "2025-01-16T15:58:50+00:00" }, { "name": "utopia-php/image", diff --git a/src/Appwrite/GraphQL/Schema.php b/src/Appwrite/GraphQL/Schema.php index 833ea9d032..5709310a6a 100644 --- a/src/Appwrite/GraphQL/Schema.php +++ b/src/Appwrite/GraphQL/Schema.php @@ -98,27 +98,36 @@ class Schema foreach ($routes as $route) { /** @var Route $route */ - $namespace = $route->getLabel('sdk.namespace', ''); - $method = $route->getLabel('sdk.method', ''); - $name = $namespace . \ucfirst($method); + /** @var \Appwrite\SDK\Method $sdk */ + $sdk = $route->getLabel('sdk', false); - if (empty($name)) { + if (empty($sdk)) { continue; } - foreach (Mapper::route($utopia, $route, $complexity) as $field) { - switch ($route->getMethod()) { - case 'GET': - $queries[$name] = $field; - break; - case 'POST': - case 'PUT': - case 'PATCH': - case 'DELETE': - $mutations[$name] = $field; - break; - default: - throw new \Exception("Unsupported method: {$route->getMethod()}"); + if (!\is_array($sdk)) { + $sdk = [$sdk]; + } + + foreach ($sdk as $method) { + $namespace = $method->getNamespace(); + $methodName = $method->getMethodName(); + $name = $namespace . \ucfirst($methodName); + + foreach (Mapper::route($utopia, $route, $method, $complexity) as $field) { + switch ($route->getMethod()) { + case 'GET': + $queries[$name] = $field; + break; + case 'POST': + case 'PUT': + case 'PATCH': + case 'DELETE': + $mutations[$name] = $field; + break; + default: + throw new \Exception("Unsupported method: {$route->getMethod()}"); + } } } } @@ -266,4 +275,4 @@ class Schema { self::$dirty[$projectId] = true; } -} +} \ No newline at end of file diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index d8f1d7da09..deae9b5270 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -4,6 +4,7 @@ namespace Appwrite\GraphQL\Types; use Appwrite\GraphQL\Resolvers; use Appwrite\GraphQL\Types; +use Appwrite\SDK\Method; use Exception; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; @@ -78,6 +79,7 @@ class Mapper public static function route( App $utopia, Route $route, + Method $method, callable $complexity ): iterable { foreach (self::$blacklist as $blacklist) { @@ -86,10 +88,27 @@ class Mapper } } - $names = $route->getLabel('sdk.response.model', 'none'); - $models = \is_array($names) - ? \array_map(static fn ($m) => static::$models[$m], $names) - : [static::$models[$names]]; + $responses = $method->getResponses() ?? []; + + // If responses is an array, map each response to its model + if (\is_array($responses)) { + $models = []; + foreach ($responses as $response) { + $modelName = $response->getModel(); + + if (\is_array($modelName)) { + foreach ($modelName as $name) { + $models[] = static::$models[$name]; + } + } else { + $models[] = static::$models[$modelName]; + } + } + } else { + // If single response, get its model and wrap in array + $modelName = $responses->getModel(); + $models = [static::$models[$modelName]]; + } foreach ($models as $model) { $type = Mapper::model(\ucfirst($model->getType())); @@ -98,13 +117,25 @@ class Mapper $list = false; foreach ($route->getParams() as $name => $parameter) { + $methodParameters = $method->getParameters(); + + if (!empty($methodParameters)) { + if (!array_key_exists($name, $methodParameters)) { + continue; + } + $optional = $methodParameters[$name]['optional']; + } else { + $optional = $parameter['optional']; + } + if ($name === 'queries') { $list = true; } + $parameterType = Mapper::param( $utopia, $parameter['validator'], - !$parameter['optional'], + !$optional, $parameter['injections'] ); $params[$name] = [ @@ -442,4 +473,4 @@ class Mapper throw new Exception('Unknown hash options implementation'); } -} +} \ No newline at end of file diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index 0f1332d821..bfc47cb69b 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Tasks; +use Appwrite\SDK\AuthType; use Appwrite\Specification\Format\OpenAPI3; use Appwrite\Specification\Format\Swagger2; use Appwrite\Specification\Specification; @@ -182,56 +183,69 @@ class Specs extends Action foreach ($appRoutes as $key => $method) { foreach ($method as $route) { - $hide = $route->getLabel('sdk.hide', false); - if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) { + $sdks = $route->getLabel('sdk', false); + + if (empty($sdks)) { continue; } - /** @var \Utopia\Route $route */ - $routeSecurity = $route->getLabel('sdk.auth', []); - $sdkPlatforms = []; + if (!\is_array($sdks)) { + $sdks = [$sdks]; + } - foreach ($routeSecurity as $value) { - switch ($value) { - case APP_AUTH_TYPE_SESSION: - $sdkPlatforms[] = APP_PLATFORM_CLIENT; - break; - case APP_AUTH_TYPE_JWT: - case APP_AUTH_TYPE_KEY: - $sdkPlatforms[] = APP_PLATFORM_SERVER; - break; - case APP_AUTH_TYPE_ADMIN: - $sdkPlatforms[] = APP_PLATFORM_CONSOLE; - break; + foreach ($sdks as $sdk) { + /** @var \Appwrite\SDK\Method $sdks */ + + $hide = $sdk->isHidden(); + if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) { + continue; } - } - if (empty($routeSecurity)) { - $sdkPlatforms[] = APP_PLATFORM_SERVER; - $sdkPlatforms[] = APP_PLATFORM_CLIENT; - } + $routeSecurity = $sdk->getAuth(); + $sdkPlatforms = []; - if (!$route->getLabel('docs', true)) { - continue; - } + foreach ($routeSecurity as $value) { + switch ($value) { + case AuthType::SESSION: + $sdkPlatforms[] = APP_PLATFORM_CLIENT; + break; + case AuthType::JWT: + case AuthType::KEY: + $sdkPlatforms[] = APP_PLATFORM_SERVER; + break; + case AuthType::ADMIN: + $sdkPlatforms[] = APP_PLATFORM_CONSOLE; + break; + } + } - if ($route->getLabel('sdk.mock', false) && !$mocks) { - continue; - } + if (empty($routeSecurity)) { + $sdkPlatforms[] = APP_PLATFORM_SERVER; + $sdkPlatforms[] = APP_PLATFORM_CLIENT; + } - if (!$route->getLabel('sdk.mock', false) && $mocks) { - continue; - } + if (!$route->getLabel('docs', true)) { + continue; + } - if (empty($route->getLabel('sdk.namespace', null))) { - continue; - } + if ($route->getLabel('mock', false) && !$mocks) { + continue; + } - if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatforms)) { - continue; - } + if (!$route->getLabel('mock', false) && $mocks) { + continue; + } - $routes[] = $route; + if (empty($sdk->getNamespace())) { + continue; + } + + if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatforms)) { + continue; + } + + $routes[] = $route; + } } } @@ -310,4 +324,4 @@ class Specs extends Action } } } -} +} \ No newline at end of file diff --git a/src/Appwrite/SDK/AuthType.php b/src/Appwrite/SDK/AuthType.php new file mode 100644 index 0000000000..e2ae5ead4d --- /dev/null +++ b/src/Appwrite/SDK/AuthType.php @@ -0,0 +1,11 @@ +<?php + +namespace Appwrite\SDK; + +enum AuthType: string +{ + case JWT = APP_AUTH_TYPE_JWT; + case KEY = APP_AUTH_TYPE_KEY; + case SESSION = APP_AUTH_TYPE_SESSION; + case ADMIN = APP_AUTH_TYPE_ADMIN; +} \ No newline at end of file diff --git a/src/Appwrite/SDK/ContentType.php b/src/Appwrite/SDK/ContentType.php new file mode 100644 index 0000000000..83a485bf17 --- /dev/null +++ b/src/Appwrite/SDK/ContentType.php @@ -0,0 +1,15 @@ +<?php + +namespace Appwrite\SDK; + +enum ContentType: string +{ + case NONE = ''; + case JSON = 'application/json'; + case IMAGE = 'image/*'; + case IMAGE_PNG = 'image/png'; + case MULTIPART = 'multipart/form-data'; + case HTML = 'text/html'; + case TEXT = 'text/plain'; + case ANY = '*/*'; +} \ No newline at end of file diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php new file mode 100644 index 0000000000..fa4f6239c1 --- /dev/null +++ b/src/Appwrite/SDK/Method.php @@ -0,0 +1,276 @@ +<?php + +namespace Appwrite\SDK; + +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Swoole\Http\Response as HttpResponse; + +class Method +{ + public static array $processed = []; + + public static array $errors = []; + + /** + * Initialise a new SDK method + * + * @param string $namespace + * @param string $name + * @param string $description + * @param array<AuthType> $auth + * @param array<SDKResponse> $responses + * @param ContentType $responseType + * @param MethodType|null $methodType + * @param bool $deprecated + * @param array|bool $hide + * @param bool $packaging + * @param string $requestType + * @param array $parameters + * @param array $additionalParameters + * + * @throws \Exception + */ + public function __construct( + protected string $namespace, + protected string $name, + protected string $description, + protected array $auth, + protected array $responses, + protected ContentType $contentType = ContentType::JSON, + protected ?MethodType $type = null, + protected bool $deprecated = false, + protected array|bool $hide = false, + protected bool $packaging = false, + protected string $requestType = 'application/json', + protected array $parameters = [], + protected array $additionalParameters = [] + ) { + $this->validateMethod($name, $namespace); + $this->validateAuthTypes($auth); + //$this->validateDesc($description); + + foreach ($responses as $response) { + /** @var SDKResponse $response */ + $this->validateResponseModel($response->getModel()); + $this->validateNoContent($response); + } + } + + private function getRouteName(): string + { + return $this->namespace . '.' . $this->name; + } + + private function validateMethod(string $name, string $namespace): void + { + if (\in_array($this->getRouteName(), self::$processed)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Method already exists in namespace {$namespace}"; + } + + self::$processed[] = $this->getRouteName(); + } + + private function validateAuthTypes(array $authTypes): void + { + foreach ($authTypes as $authType) { + if (!($authType instanceof AuthType)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Invalid auth type"; + } + } + } + + private function validateDesc(string $desc): void + { + if (empty($desc)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Description label is empty"; + return; + } + + $descPath = \realpath(__DIR__ . '/../../../' . $desc); + + if (!\file_exists($descPath)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Description file not found at {$desc}"; + return; + } + } + + private function validateResponseModel(string|array $responseModel): void + { + $response = new Response(new HttpResponse()); + + if (!\is_array($responseModel)) { + $responseModel = [$responseModel]; + } + + foreach ($responseModel as $model) { + try { + $response->getModel($model); + } catch (\Exception $e) { + self::$errors[] = "Error with {$this->getRouteName()} method: Invalid response model, make sure the model has been defined in Response.php"; + } + } + } + + private function validateNoContent(SDKResponse $response): void + { + if ($response->getCode() === 204) { + if ($response->getModel() !== Response::MODEL_NONE) { + self::$errors[] = "Error with {$this->getRouteName()} method: Response code 204 must have response model 'none'"; + } + } + } + + public function getNamespace(): string + { + return $this->namespace; + } + + public function getMethodName(): string + { + return $this->name; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getAuth(): array + { + return $this->auth; + } + + /** + * @return array<SDKResponse> + */ + public function getResponses(): array + { + return $this->responses; + } + + public function getContentType(): ContentType + { + return $this->contentType; + } + + public function getType(): ?MethodType + { + return $this->type; + } + + public function isDeprecated(): bool + { + return $this->deprecated; + } + + public function isHidden(): bool|array + { + return $this->hide ?? false; + } + + public function isPackaging(): bool + { + return $this->packaging; + } + + public function getRequestType(): string + { + return $this->requestType; + } + + public function getParameters(): array + { + return $this->parameters; + } + + public function getAdditionalParameters(): array + { + return $this->additionalParameters; + } + + public function setNamespace(string $namespace): self + { + $this->namespace = $namespace; + return $this; + } + + public function setMethodName(string $name): self + { + $this->name = $name; + return $this; + } + + public function setDescription(string $description): self + { + $this->description = $description; + return $this; + } + + public function setAuth(array $auth): self + { + $this->validateAuthTypes($auth); + $this->auth = $auth; + return $this; + } + + /** + * @param array<SDKResponse> $responses + */ + public function setResponses(array $responses): self + { + foreach ($responses as $response) { + $this->validateResponseModel($response->getModel()); + $this->validateNoContent($response); + } + $this->responses = $responses; + return $this; + } + + public function setContentType(ContentType $contentType): self + { + $this->contentType = $contentType; + return $this; + } + + public function setType(?MethodType $type): self + { + $this->type = $type; + return $this; + } + + public function setDeprecated(bool $deprecated): self + { + $this->deprecated = $deprecated; + return $this; + } + + public function setHide(bool|array $hide): self + { + $this->hide = $hide; + return $this; + } + + public function setPackaging(bool $packaging): self + { + $this->packaging = $packaging; + return $this; + } + + public function setRequestType(string $requestType): self + { + $this->requestType = $requestType; + return $this; + } + + public function setParameters(array $parameters): self + { + $this->parameters = $parameters; + return $this; + } + + public static function getErrors(): array + { + return self::$errors; + } +} \ No newline at end of file diff --git a/src/Appwrite/SDK/MethodType.php b/src/Appwrite/SDK/MethodType.php new file mode 100644 index 0000000000..b4982c847a --- /dev/null +++ b/src/Appwrite/SDK/MethodType.php @@ -0,0 +1,11 @@ +<?php + +namespace Appwrite\SDK; + +enum MethodType: string +{ + case WEBAUTH = 'webAuth'; + case LOCATION = 'location'; + case GRAPHQL = 'graphql'; + case UPLOAD = 'upload'; +} \ No newline at end of file diff --git a/src/Appwrite/SDK/Response.php b/src/Appwrite/SDK/Response.php new file mode 100644 index 0000000000..e2b3cab4d0 --- /dev/null +++ b/src/Appwrite/SDK/Response.php @@ -0,0 +1,27 @@ +<?php + +namespace Appwrite\SDK; + +class Response +{ + /** + * @param int $code + * @param string|array $model + * @param string $description + */ + public function __construct( + private int $code, + private string|array $model + ) { + } + + public function getCode(): int + { + return $this->code; + } + + public function getModel(): string|array + { + return $this->model; + } +} \ No newline at end of file diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 65df0cb694..8aae96f92c 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -2,6 +2,8 @@ namespace Appwrite\Specification\Format; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\MethodType; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; @@ -120,28 +122,49 @@ class OpenAPI3 extends Format foreach ($this->routes as $route) { $url = \str_replace('/v1', '', $route->getPath()); $scope = $route->getLabel('scope', ''); - $consumes = [$route->getLabel('sdk.request.type', 'application/json')]; + $sdk = $route->getLabel('sdk', false); - $method = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; - $produces = $route->getLabel('sdk.response.type', null); - $model = $route->getLabel('sdk.response.model', 'none'); - $routeSecurity = $route->getLabel('sdk.auth', []); + if (empty($sdk)) { + continue; + } + + $additionalMethods = null; + if (is_array($sdk)) { + $mainSdk = array_shift($sdk); + $additionalMethods = $sdk; + + $sdk = $mainSdk; + } + + /** + * @var \Appwrite\SDK\Method $sdk + */ + $consumes = [$sdk->getRequestType()]; + + $method = $sdk->getMethodName() ?? \uniqid(); + + if (!empty($method) && is_array($method)) { + $method = array_keys($method)[0]; + } + + $desc = (!empty($sdk->getDescription())) ? \realpath(__DIR__ . '/../../../../' . $sdk->getDescription()) : null; + $produces = ($sdk->getContentType())->value; + $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; foreach ($routeSecurity as $value) { switch ($value) { - case APP_AUTH_TYPE_SESSION: + case AuthType::SESSION: $sdkPlatforms[] = APP_PLATFORM_CLIENT; break; - case APP_AUTH_TYPE_KEY: + case AuthType::KEY: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_JWT: + case AuthType::JWT: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_ADMIN: + case AuthType::ADMIN: $sdkPlatforms[] = APP_PLATFORM_CONSOLE; break; } @@ -152,102 +175,140 @@ class OpenAPI3 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } + $namespace = $sdk->getNamespace() ?? 'default'; + $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($method), - 'tags' => [$route->getLabel('sdk.namespace', 'default')], + 'operationId' => $namespace . ucfirst($method), + 'tags' => [$namespace], 'description' => ($desc) ? \file_get_contents($desc) : '', 'responses' => [], 'x-appwrite' => [ // Appwrite related metadata 'method' => $method, 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), - 'type' => $route->getLabel('sdk.methodType', ''), - 'deprecated' => $route->getLabel('sdk.deprecated', false), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($method) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'type' => $sdk->getType()->value ?? '', + 'deprecated' => $sdk->isDeprecated(), + 'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($method) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $sdk->getDescription() ?? '', 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'scope' => $route->getLabel('scope', ''), 'platforms' => $sdkPlatforms, - 'packaging' => $route->getLabel('sdk.packaging', false), - 'offline-model' => $route->getLabel('sdk.offline.model', ''), - 'offline-key' => $route->getLabel('sdk.offline.key', ''), - 'offline-response-key' => $route->getLabel('sdk.offline.response.key', '$id'), + 'packaging' => $sdk->isPackaging() ], ]; - foreach ($this->models as $value) { - if (\is_array($model)) { - $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); - } else { - if ($value->getType() === $model) { - $model = $value; - break; + + if (!empty($additionalMethods)) { + $temp['x-appwrite']['additional-methods'] = []; + foreach ($additionalMethods as $method) { + /** @var \Appwrite\SDK\Method $method */ + $additionalMethod = [ + 'name' => $method->getMethodName(), + 'parameters' => [], + 'required' => [], + 'responses' => [] + ]; + + foreach ($method->getParameters() as $name => $param) { + $additionalMethod['parameters'][] = $name; + + if (!$param['optional']) { + $additionalMethod['required'][] = $name; + } } + + foreach ($method->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $additionalMethod['responses'][] = [ + 'code' => $response->getCode(), + 'model' => '#/components/schemas/' . $response->getModel() + ]; + } + + $temp['x-appwrite']['additional-methods'][] = $additionalMethod; } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => in_array($produces, [ - 'image/*', - 'image/jpeg', - 'image/gif', - 'image/png', - 'image/webp', - 'image/svg-x', - 'image/x-icon', - 'image/bmp', - ]) ? 'Image' : 'File', - ]; - } else { - if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + // Handle response models + foreach ($sdk->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $model = $response->getModel(); - // model has multiple possible responses, we will use oneOf - foreach ($model as $m) { - $usedModels[] = $m->getType(); + foreach ($this->models as $value) { + if (\is_array($model)) { + $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); + } else { + if ($value->getType() === $model) { + $model = $value; + break; + } } + } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $modelDescription, - 'content' => [ - $produces => [ - 'schema' => [ - 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) - ], - ], - ], + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => in_array($produces, [ + 'image/*', + 'image/jpeg', + 'image/gif', + 'image/png', + 'image/webp', + 'image/svg-x', + 'image/x-icon', + 'image/bmp', + ]) ? 'Image' : 'File', ]; } else { - // Response definition using one type - $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $model->getName(), - 'content' => [ - $produces => [ - 'schema' => [ - '$ref' => '#/components/schemas/' . $model->getType(), + if (\is_array($model)) { + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + + // model has multiple possible responses, we will use oneOf + foreach ($model as $m) { + $usedModels[] = $m->getType(); + } + + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $modelDescription, + 'content' => [ + $produces => [ + 'schema' => [ + 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) + ], ], ], - ], - ]; + ]; + } else { + // Response definition using one type + $usedModels[] = $model->getType(); + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $model->getName(), + 'content' => [ + $produces => [ + 'schema' => [ + '$ref' => '#/components/schemas/' . $model->getType(), + ], + ], + ], + ]; + } } - } - if ($route->getLabel('sdk.response.code', 500) === 204) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + if (($response->getCode() ?? 500) === 204) { + $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content'; + unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']); + } } if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach ($route->getLabel('sdk.auth', []) as $security) { - if (array_key_exists($security, $this->keys)) { - $securities[$security] = []; + foreach ($sdk->getAuth() as $security) { + /** @var \Appwrite\SDK\AuthType $security */ + if (array_key_exists($security->value, $this->keys)) { + $securities[$security->value] = []; } } @@ -298,7 +359,7 @@ class OpenAPI3 extends Format $node['schema']['x-example'] = false; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if ($route->getLabel('sdk.methodType', '') === 'upload') { + if ($sdk->getType() === MethodType::UPLOAD) { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); @@ -323,7 +384,6 @@ class OpenAPI3 extends Format case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': - case 'Appwrite\Functions\Validator\Payload': $param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default']; $node['schema']['type'] = 'object'; $node['schema']['x-example'] = '{}'; @@ -423,7 +483,7 @@ class OpenAPI3 extends Format $allowed = true; foreach ($this->enumBlacklist as $blacklist) { if ( - $blacklist['namespace'] == $route->getLabel('sdk.namespace', '') + $blacklist['namespace'] == $sdk->getNamespace() && $blacklist['method'] == $method && $blacklist['parameter'] == $name ) { @@ -434,8 +494,8 @@ class OpenAPI3 extends Format if ($allowed) { $node['schema']['enum'] = $validator->getList(); - $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $method, $name); - $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $method, $name); + $node['schema']['x-enum-name'] = $this->getEnumName($sdk->getNamespace() ?? '', $method, $name); + $node['schema']['x-enum-keys'] = $this->getEnumKeys($sdk->getNamespace() ?? '', $method, $name); } if ($validator->getType() === 'integer') { $node['format'] = 'int32'; @@ -641,4 +701,4 @@ class OpenAPI3 extends Format return $output; } -} +} \ No newline at end of file diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index b10188525e..4760da8b40 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -2,6 +2,8 @@ namespace Appwrite\Specification\Format; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\MethodType; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; @@ -34,6 +36,7 @@ class Swagger2 extends Format foreach ($this->models as $m) { if ($m->getType() === $ruleType) { $this->getNestedModels($m, $usedModels); + continue; } } } @@ -45,6 +48,7 @@ class Swagger2 extends Format foreach ($this->models as $m) { if ($m->getType() === $rule['type']) { $this->getNestedModels($m, $usedModels); + continue; } } } @@ -116,27 +120,47 @@ class Swagger2 extends Format /** @var \Utopia\Route $route */ $url = \str_replace('/v1', '', $route->getPath()); $scope = $route->getLabel('scope', ''); - $consumes = [$route->getLabel('sdk.request.type', 'application/json')]; - $method = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; - $produces = $route->getLabel('sdk.response.type', null); - $model = $route->getLabel('sdk.response.model', 'none'); - $routeSecurity = $route->getLabel('sdk.auth', []); + /** @var \Appwrite\SDK\Method $sdk */ + $sdk = $route->getLabel('sdk', false); + + if (empty($sdk)) { + continue; + } + + $additionalMethods = null; + if (is_array($sdk)) { + $mainSdk = array_shift($sdk); + $additionalMethods = $sdk; + + $sdk = $mainSdk; + } + + $consumes = [$sdk->getRequestType()]; + + $method = $sdk->getMethodName() ?? \uniqid(); + + if (!empty($method) && is_array($method)) { + $method = array_keys($method)[0]; + } + + $desc = (!empty($sdk->getDescription())) ? \realpath(__DIR__ . '/../../../../' . $sdk->getDescription()) : null; + $produces = ($sdk->getContentType())->value; + $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; foreach ($routeSecurity as $value) { switch ($value) { - case APP_AUTH_TYPE_SESSION: + case AuthType::SESSION: $sdkPlatforms[] = APP_PLATFORM_CLIENT; break; - case APP_AUTH_TYPE_KEY: + case AuthType::KEY: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_JWT: + case AuthType::JWT: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_ADMIN: + case AuthType::ADMIN: $sdkPlatforms[] = APP_PLATFORM_CONSOLE; break; } @@ -147,31 +171,30 @@ class Swagger2 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } + $namespace = $sdk->getNamespace() ?? 'default'; + $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($method), + 'operationId' => $namespace . ucfirst($method), 'consumes' => [], 'produces' => [], - 'tags' => [$route->getLabel('sdk.namespace', 'default')], + 'tags' => [$namespace], 'description' => ($desc) ? \file_get_contents($desc) : '', 'responses' => [], 'x-appwrite' => [ // Appwrite related metadata 'method' => $method, 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), - 'type' => $route->getLabel('sdk.methodType', ''), - 'deprecated' => $route->getLabel('sdk.deprecated', false), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($method) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'type' => $sdk->getType()->value ?? '', + 'deprecated' => $sdk->isDeprecated(), + 'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($method) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $sdk->getDescription() ?? '', 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'scope' => $route->getLabel('scope', ''), 'platforms' => $sdkPlatforms, - 'packaging' => $route->getLabel('sdk.packaging', false), - 'offline-model' => $route->getLabel('sdk.offline.model', ''), - 'offline-key' => $route->getLabel('sdk.offline.key', ''), - 'offline-response-key' => $route->getLabel('sdk.offline.response.key', '$id'), + 'packaging' => $sdk->isPackaging() ], ]; @@ -179,71 +202,111 @@ class Swagger2 extends Format $temp['produces'][] = $produces; } - foreach ($this->models as $value) { - if (\is_array($model)) { - $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); - } else { - if ($value->getType() === $model) { - $model = $value; - break; + if (!empty($additionalMethods)) { + $temp['x-appwrite']['additional-methods'] = []; + foreach ($additionalMethods as $method) { + /** @var \Appwrite\SDK\Method $method */ + $additionalMethod = [ + 'name' => $method->getMethodName(), + 'parameters' => [], + 'required' => [], + 'responses' => [], + 'description' => $method->getDescription(), + ]; + + foreach ($method->getParameters() as $name => $param) { + $additionalMethod['parameters'][] = $name; + + if (!$param['optional']) { + $additionalMethod['required'][] = $name; + } } + + foreach ($method->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $additionalMethod['responses'][] = [ + 'code' => $response->getCode(), + 'model' => '#/definitions/' . $response->getModel() + ]; + } + + $temp['x-appwrite']['additional-methods'][] = $additionalMethod; } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => in_array($produces, [ - 'image/*', - 'image/jpeg', - 'image/gif', - 'image/png', - 'image/webp', - 'image/svg-x', - 'image/x-icon', - 'image/bmp', - ]) ? 'Image' : 'File', - 'schema' => [ - 'type' => 'file' - ], - ]; - } else { - if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); - // model has multiple possible responses, we will use oneOf - foreach ($model as $m) { - $usedModels[] = $m->getType(); + // Handle Responses + + foreach ($sdk->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $model = $response->getModel(); + + foreach ($this->models as $value) { + if (\is_array($model)) { + $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); + } else { + if ($value->getType() === $model) { + $model = $value; + break; + } } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $modelDescription, + } + + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => in_array($produces, [ + 'image/*', + 'image/jpeg', + 'image/gif', + 'image/png', + 'image/webp', + 'image/svg-x', + 'image/x-icon', + 'image/bmp', + ]) ? 'Image' : 'File', 'schema' => [ - 'x-oneOf' => \array_map(function ($m) { - return ['$ref' => '#/definitions/' . $m->getType()]; - }, $model) + 'type' => 'file' ], ]; } else { - // Response definition using one type - $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $model->getName(), - 'schema' => [ - '$ref' => '#/definitions/' . $model->getType(), - ], - ]; + if (\is_array($model)) { + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + // model has multiple possible responses, we will use oneOf + foreach ($model as $m) { + $usedModels[] = $m->getType(); + } + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $modelDescription, + 'schema' => [ + 'x-oneOf' => \array_map(function ($m) { + return ['$ref' => '#/definitions/' . $m->getType()]; + }, $model) + ], + ]; + } else { + // Response definition using one type + $usedModels[] = $model->getType(); + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $model->getName(), + 'schema' => [ + '$ref' => '#/definitions/' . $model->getType(), + ], + ]; + } } - } - if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + if (in_array($response->getCode() ?? 500, [204, 301, 302, 308], true)) { + $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content'; + unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']); + } } if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach ($route->getLabel('sdk.auth', []) as $security) { - if (array_key_exists($security, $this->keys)) { - $securities[$security] = []; + foreach ($sdk->getAuth() as $security) { + /** @var \Appwrite\SDK\AuthType $security */ + if (array_key_exists($security->value, $this->keys)) { + $securities[$security->value] = []; } } @@ -264,7 +327,7 @@ class Swagger2 extends Format $parameters = \array_merge( $route->getParams(), - $route->getLabel('sdk.parameters', []), + $sdk->getAdditionalParameters() ?? [], ); foreach ($parameters as $name => $param) { // Set params @@ -314,7 +377,7 @@ class Swagger2 extends Format $node['x-example'] = false; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if ($route->getLabel('sdk.methodType', '') === 'upload') { + if ($sdk->getType() === MethodType::UPLOAD) { $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); @@ -347,7 +410,6 @@ class Swagger2 extends Format case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': - case 'Appwrite\Functions\Validator\Payload': $node['type'] = 'object'; $node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default']; $node['x-example'] = '{}'; @@ -422,7 +484,7 @@ class Swagger2 extends Format //Iterate the blackList. If it matches with the current one, then it is blackListed $allowed = true; foreach ($this->enumBlacklist as $blacklist) { - if ($blacklist['namespace'] == $route->getLabel('sdk.namespace', '') && $blacklist['method'] == $method && $blacklist['parameter'] == $name) { + if ($blacklist['namespace'] == $namespace && $blacklist['method'] == $method && $blacklist['parameter'] == $name) { $allowed = false; break; } @@ -430,8 +492,8 @@ class Swagger2 extends Format if ($allowed && $validator->getType() === 'string') { $node['enum'] = $validator->getList(); - $node['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $method, $name); - $node['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $method, $name); + $node['x-enum-name'] = $this->getEnumName($namespace, $method, $name); + $node['x-enum-keys'] = $this->getEnumKeys($namespace, $method, $name); } if ($validator->getType() === 'integer') { @@ -649,4 +711,4 @@ class Swagger2 extends Format return $output; } -} +} \ No newline at end of file diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 26c1baf188..f8c0439293 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -28,8 +28,30 @@ class Request extends UtopiaRequest $parameters = parent::getParams(); if ($this->hasFilters() && self::hasRoute()) { - $method = self::getRoute()->getLabel('sdk.method', 'unknown'); - $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown') . '.' . $method; + $methods = self::getRoute()->getLabel('sdk', null); + + if (!\is_array($methods)) { + $methods = [$methods]; + } + + $params = []; + + foreach ($methods as $method) { + /** @var \Appwrite\SDK\Method $method */ + if (empty($method)) { + $endpointIdentifier = 'unknown.unknown'; + } else { + $endpointIdentifier = $method->getNamespace() . '.' . $method->getMethodName(); + } + + $params += $method->getParameters(); + } + + if (!empty($params)) { + $parameters = array_filter($parameters, function ($key) use ($params) { + return array_key_exists($key, $params); + }, \ARRAY_FILTER_USE_KEY); + } foreach ($this->getFilters() as $filter) { $parameters = $filter->parse($parameters, $endpointIdentifier); diff --git a/tests/unit/Utopia/RequestTest.php b/tests/unit/Utopia/RequestTest.php index 73daaa88bc..e19fdbe01f 100644 --- a/tests/unit/Utopia/RequestTest.php +++ b/tests/unit/Utopia/RequestTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Utopia; +use Appwrite\SDK\Method; use Appwrite\Utopia\Request; use PHPUnit\Framework\TestCase; use Swoole\Http\Request as SwooleRequest; @@ -31,8 +32,13 @@ class RequestTest extends TestCase $this->assertCount(2, $this->request->getFilters()); $route = new Route(Request::METHOD_GET, '/test'); - $route->label('sdk.method', 'method'); - $route->label('sdk.namespace', 'namespace'); + $route->label('sdk', new Method( + namespace: 'namespace', + name: 'method', + description: 'description', + auth: [], + responses: [], + )); // set test header to prevent header populaten inside the request class $this->request->addHeader('EXAMPLE', 'VALUE'); $this->request->setRoute($route); From d5604efef8cea5bacedc542bcbf38be01735a468 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Fri, 17 Jan 2025 13:38:38 +0900 Subject: [PATCH 308/340] Fix actions --- app/controllers/api/vcs.php | 1 - app/controllers/general.php | 7 ++++++- app/http.php | 9 ++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index e64a2f895b..7c31d93df5 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -272,7 +272,6 @@ App::get('/v1/vcs/github/authorize') ->desc('Install GitHub app') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('sdk', new Method( namespace: 'vcs', diff --git a/app/controllers/general.php b/app/controllers/general.php index f6a584b69e..aedecf8a9c 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -931,7 +931,12 @@ App::error() $log->addExtra('trace', $error->getTraceAsString()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; + if (!empty($sdk)) { + /** @var Appwrite\SDK\Method $sdk */ + $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); + } + $log->setAction($action); $log->addTag('service', $action); diff --git a/app/http.php b/app/http.php index 3a7562ffd1..e85120a894 100644 --- a/app/http.php +++ b/app/http.php @@ -386,7 +386,14 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $log->addExtra('trace', $th->getTraceAsString()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $sdk = $route->getLabel("sdk", false); + + $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; + if (!empty($sdk)) { + /** @var Appwrite\SDK\Method $sdk */ + $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); + } + $log->setAction($action); $log->addTag('service', $action); From 20e87cb82f3725547b67c3d8de7604251571592e Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Fri, 17 Jan 2025 13:39:16 +0900 Subject: [PATCH 309/340] Run Linter --- app/controllers/api/account.php | 2 +- app/controllers/api/avatars.php | 2 +- app/controllers/api/console.php | 2 +- app/controllers/api/databases.php | 2 +- app/controllers/api/functions.php | 2 +- app/controllers/api/graphql.php | 2 +- app/controllers/api/health.php | 2 +- app/controllers/api/locale.php | 2 +- app/controllers/api/messaging.php | 2 +- app/controllers/api/migrations.php | 9 +-------- app/controllers/api/project.php | 2 +- app/controllers/api/projects.php | 2 +- app/controllers/api/storage.php | 2 +- app/controllers/api/teams.php | 2 +- app/controllers/api/users.php | 2 +- app/controllers/general.php | 2 +- src/Appwrite/GraphQL/Schema.php | 2 +- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- src/Appwrite/Platform/Tasks/Specs.php | 2 +- src/Appwrite/SDK/AuthType.php | 2 +- src/Appwrite/SDK/ContentType.php | 2 +- src/Appwrite/SDK/Method.php | 2 +- src/Appwrite/SDK/MethodType.php | 2 +- src/Appwrite/SDK/Response.php | 2 +- src/Appwrite/Specification/Format/OpenAPI3.php | 2 +- src/Appwrite/Specification/Format/Swagger2.php | 2 +- 26 files changed, 26 insertions(+), 33 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 727ed746a4..80c2b69ba3 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4894,4 +4894,4 @@ App::delete('/v1/account/identities/:identityId') ->setPayload($response->output($identity, Response::MODEL_IDENTITY)); return $response->noContent(); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 2b0f7d9e06..94a3fb374d 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1276,4 +1276,4 @@ App::get('/v1/cards/cloud-og') ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days ->setContentType('image/png') ->file($baseImage->getImageBlob()); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 77ba67e6e1..9a41f67724 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -125,4 +125,4 @@ App::post('/v1/console/assistant') curl_close($ch); $response->chunk('', true); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index b4635128c3..4107614fa0 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4415,4 +4415,4 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') 'documentsTotal' => $usage[$metrics[0]]['total'], 'documents' => $usage[$metrics[0]]['data'], ]), Response::MODEL_USAGE_COLLECTION); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 9b6f92ed5b..205f96072e 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -2851,4 +2851,4 @@ App::get('/v1/functions/templates/:templateId') } $response->dynamic(new Document($template), Response::MODEL_TEMPLATE_FUNCTION); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index 80a17db7cb..72951b608e 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -331,4 +331,4 @@ App::shutdown() ->inject('project') ->action(function (Document $project) { Schema::setDirty($project->getId()); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 787bc71ac8..1db4713311 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -1054,4 +1054,4 @@ App::get('/v1/health/stats') // Currently only used internally 'memory_used_peak_human' => $cacheStats['used_memory_peak_human'] ?? 0, ], ]); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/locale.php b/app/controllers/api/locale.php index 65f719f914..5b4c1ac47f 100644 --- a/app/controllers/api/locale.php +++ b/app/controllers/api/locale.php @@ -294,4 +294,4 @@ App::get('/v1/locale/languages') $list = array_map(fn ($node) => new Document($node), $list); $response->dynamic(new Document(['languages' => $list, 'total' => \count($list)]), Response::MODEL_LANGUAGE_LIST); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index c80da75801..d7d3750ccf 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -4254,4 +4254,4 @@ App::delete('/v1/messaging/messages/:messageId') ->setPayload($response->output($message, Response::MODEL_MESSAGE)); $response->noContent(); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 670628de62..ac149ac8eb 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -3,19 +3,14 @@ use Appwrite\Event\Event; use Appwrite\Event\Migration; use Appwrite\Extend\Exception; -use Appwrite\Permission; -use Appwrite\Role; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; -use Appwrite\SDK\MethodType; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Migrations; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; @@ -26,9 +21,7 @@ use Utopia\Migration\Sources\Appwrite; use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; -use Utopia\System\System; use Utopia\Validator\ArrayList; -use Utopia\Validator\Host; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -673,4 +666,4 @@ App::delete('/v1/migrations/:migrationId') $queueForEvents->setParam('migrationId', $migration->getId()); $response->noContent(); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 50ef982799..2fc6578c2b 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -570,4 +570,4 @@ App::delete('/v1/project/variables/:variableId') } $response->noContent(); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 896e708327..c40d7601c4 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -2429,4 +2429,4 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') 'replyTo' => $template['replyTo'], 'message' => $template['message'] ]), Response::MODEL_EMAIL_TEMPLATE); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 8ed7aaff22..49f8897884 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1942,4 +1942,4 @@ App::get('/v1/storage/:bucketId/usage') 'files' => $usage[$metrics[0]]['data'], 'storage' => $usage[$metrics[1]]['data'], ]), Response::MODEL_USAGE_BUCKETS); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 612df0d439..9250f0c6b1 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1408,4 +1408,4 @@ App::get('/v1/teams/:teamId/logs') 'total' => $audit->countLogsByResource($resource), 'logs' => $output, ]), Response::MODEL_LOG_LIST); - }); \ No newline at end of file + }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 9c3026793b..d2c840d368 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2465,4 +2465,4 @@ App::get('/v1/users/usage') 'users' => $usage[$metrics[0]]['data'], 'sessions' => $usage[$metrics[1]]['data'], ]), Response::MODEL_USAGE_USERS); - }); \ No newline at end of file + }); diff --git a/app/controllers/general.php b/app/controllers/general.php index aedecf8a9c..8e282cb0e4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1180,4 +1180,4 @@ foreach (Config::getParam('services', []) as $service) { // Check for any errors found while we were initialising the SDK Methods. if (!empty(Method::getErrors())) { throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors())); -} \ No newline at end of file +} diff --git a/src/Appwrite/GraphQL/Schema.php b/src/Appwrite/GraphQL/Schema.php index 5709310a6a..a0d93de45c 100644 --- a/src/Appwrite/GraphQL/Schema.php +++ b/src/Appwrite/GraphQL/Schema.php @@ -275,4 +275,4 @@ class Schema { self::$dirty[$projectId] = true; } -} \ No newline at end of file +} diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index deae9b5270..e5056d0abc 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -473,4 +473,4 @@ class Mapper throw new Exception('Unknown hash options implementation'); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index bfc47cb69b..4d7fd5d695 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -324,4 +324,4 @@ class Specs extends Action } } } -} \ No newline at end of file +} diff --git a/src/Appwrite/SDK/AuthType.php b/src/Appwrite/SDK/AuthType.php index e2ae5ead4d..307b3cf35e 100644 --- a/src/Appwrite/SDK/AuthType.php +++ b/src/Appwrite/SDK/AuthType.php @@ -8,4 +8,4 @@ enum AuthType: string case KEY = APP_AUTH_TYPE_KEY; case SESSION = APP_AUTH_TYPE_SESSION; case ADMIN = APP_AUTH_TYPE_ADMIN; -} \ No newline at end of file +} diff --git a/src/Appwrite/SDK/ContentType.php b/src/Appwrite/SDK/ContentType.php index 83a485bf17..174c889815 100644 --- a/src/Appwrite/SDK/ContentType.php +++ b/src/Appwrite/SDK/ContentType.php @@ -12,4 +12,4 @@ enum ContentType: string case HTML = 'text/html'; case TEXT = 'text/plain'; case ANY = '*/*'; -} \ No newline at end of file +} diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php index fa4f6239c1..8064b75561 100644 --- a/src/Appwrite/SDK/Method.php +++ b/src/Appwrite/SDK/Method.php @@ -273,4 +273,4 @@ class Method { return self::$errors; } -} \ No newline at end of file +} diff --git a/src/Appwrite/SDK/MethodType.php b/src/Appwrite/SDK/MethodType.php index b4982c847a..2b1f786779 100644 --- a/src/Appwrite/SDK/MethodType.php +++ b/src/Appwrite/SDK/MethodType.php @@ -8,4 +8,4 @@ enum MethodType: string case LOCATION = 'location'; case GRAPHQL = 'graphql'; case UPLOAD = 'upload'; -} \ No newline at end of file +} diff --git a/src/Appwrite/SDK/Response.php b/src/Appwrite/SDK/Response.php index e2b3cab4d0..e87813024b 100644 --- a/src/Appwrite/SDK/Response.php +++ b/src/Appwrite/SDK/Response.php @@ -24,4 +24,4 @@ class Response { return $this->model; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 8aae96f92c..02568a8ccf 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -701,4 +701,4 @@ class OpenAPI3 extends Format return $output; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 4760da8b40..22aac47113 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -711,4 +711,4 @@ class Swagger2 extends Format return $output; } -} \ No newline at end of file +} From 8bdafb46d6d39a23c5ad6624758de129c953b4d6 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 10:38:39 +0530 Subject: [PATCH 310/340] chore: review comments & refactoring --- app/controllers/api/functions.php | 4 ++ phpunit.xml | 2 +- src/Appwrite/Event/Audit.php | 20 ++----- src/Appwrite/Event/Build.php | 20 ++----- src/Appwrite/Event/Certificate.php | 20 ++----- src/Appwrite/Event/Database.php | 51 +++++++--------- src/Appwrite/Event/Delete.php | 21 ++----- src/Appwrite/Event/Event.php | 58 ++++++++++++------- src/Appwrite/Event/Func.php | 43 ++------------ src/Appwrite/Event/Mail.php | 20 ++----- src/Appwrite/Event/Messaging.php | 21 ++----- src/Appwrite/Event/Migration.php | 20 ++----- src/Appwrite/Event/Realtime.php | 3 + src/Appwrite/Event/Usage.php | 33 +++++------ src/Appwrite/Event/UsageDump.php | 19 ++---- src/Appwrite/Event/Webhook.php | 15 +++-- .../Functions/FunctionsCustomServerTest.php | 2 +- 17 files changed, 138 insertions(+), 234 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d4d5fc64cf..f459875fca 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -400,6 +400,10 @@ App::post('/v1/functions') $allEvents = Event::generateEvents('rules.[ruleId].create', [ 'ruleId' => $rule->getId(), ]); + + + var_dump("-------------------- Create Function ---------------"); + var_dump($project); $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], diff --git a/phpunit.xml b/phpunit.xml index 4c4e55ea4e..598b730908 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > <extensions> <extension class="Appwrite\Tests\TestHook" /> diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 5cbe379666..4b9aa9f5c5 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -2,7 +2,6 @@ namespace Appwrite\Event; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Audit extends Event @@ -139,22 +138,13 @@ class Audit extends Event } /** - * Executes the event and sends it to the audit worker. + * Prepare payload for queue. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'user' => $this->user, 'payload' => $this->payload, @@ -164,6 +154,6 @@ class Audit extends Event 'userAgent' => $this->userAgent, 'event' => $this->event, 'hostname' => $this->hostname - ]); + ]; } } diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index bdbcf6826c..831adf8e41 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Build extends Event @@ -105,28 +104,19 @@ class Build extends Event } /** - * Executes the function event and sends it to the functions worker. + * Prepare payload for queue. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'resource' => $this->resource, 'deployment' => $this->deployment, 'type' => $this->type, 'template' => $this->template - ]); + ]; } /** diff --git a/src/Appwrite/Event/Certificate.php b/src/Appwrite/Event/Certificate.php index 2629653c59..6a395417ed 100644 --- a/src/Appwrite/Event/Certificate.php +++ b/src/Appwrite/Event/Certificate.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Certificate extends Event @@ -67,25 +66,16 @@ class Certificate extends Event } /** - * Executes the event and sends it to the certificates worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'domain' => $this->domain, 'skipRenewCheck' => $this->skipRenewCheck - ]); + ]; } } diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index e78fe967e7..24123de6c1 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -4,7 +4,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; use Utopia\DSN\DSN; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Database extends Event @@ -100,18 +99,8 @@ class Database extends Event return $this->document; } - /** - * Executes the event and send it to the database worker. - * - * @return string|bool - * @throws \InvalidArgumentException - */ - public function trigger(): string|bool + public function getQueue(): string { - if ($this->paused) { - return false; - } - try { $dsn = new DSN($this->getProject()->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -119,25 +108,25 @@ class Database extends Event $dsn = new DSN('mysql://' . $this->getProject()->getAttribute('database')); } - $this->setQueue($dsn->getHost()); + $this->queue = $dsn->getHost(); + return $this->queue; + } - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - try { - $result = $client->enqueue([ - 'project' => $this->project, - 'user' => $this->user, - 'type' => $this->type, - 'collection' => $this->collection, - 'document' => $this->document, - 'database' => $this->database, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); - return $result; - } catch (\Throwable $th) { - return false; - } + /** + * Prepare the payload for the event + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'project' => $this->project, + 'user' => $this->user, + 'type' => $this->type, + 'collection' => $this->collection, + 'document' => $this->document, + 'database' => $this->database, + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + ]; } } diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 2874043163..f0af20f21b 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Delete extends Event @@ -131,24 +130,14 @@ class Delete extends Event return $this->document; } - /** - * Executes this event and sends it to the deletes worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'type' => $this->type, 'document' => $this->document, @@ -156,6 +145,6 @@ class Delete extends Event 'resourceType' => $this->resourceType, 'datetime' => $this->datetime, 'hourlyUsageRetentionDatetime' => $this->hourlyUsageRetentionDatetime - ]); + ]; } } diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 4efc138ec6..8dc0acbe2f 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -140,24 +140,6 @@ class Event return $this; } - /** - * Trims the fields of the project document to only include the necessary fields. - * - * @return self - */ - public function trimFields(): self - { - if ($this->project) { - $this->project = new Document([ - '$id' => $this->project->getId(), - '$internalId' => $this->project->getInternalId(), - 'database' => $this->project->getAttribute('database') - ]); - } - - return $this; - } - /** * Get project for this event. * @@ -329,6 +311,27 @@ class Event return $this->params; } + /** + * Get trimmed values for sensitive/large payload fields. + * Override this method in child classes to add more fields to trim. + * + * @return array + */ + protected function trimPayload(): array + { + $trimmed = []; + + if ($this->project) { + $trimmed['project'] = new Document([ + '$id' => $this->project->getId(), + '$internalId' => $this->project->getInternalId(), + 'database' => $this->project->getAttribute('database') + ]); + } + + return $trimmed; + } + /** * Execute Event. * @@ -341,18 +344,29 @@ class Event return false; } - $this->trimFields(); + $client = new Client($this->getQueue(), $this->connection); - $client = new Client($this->queue, $this->connection); + // Merge the base payload with any trimmed values + $payload = array_merge($this->preparePayload(), $this->trimPayload()); - return $client->enqueue([ + return $client->enqueue($payload); + } + + /** + * Prepare payload for queue. Can be overridden by child classes to customize payload. + * + * @return array + */ + protected function preparePayload(): array + { + return [ 'project' => $this->project, 'user' => $this->user, 'userId' => $this->userId, 'payload' => $this->payload, 'context' => $this->context, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); + ]; } /** diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 7c6a2e9194..2e72cb86bf 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Func extends Event @@ -172,29 +171,6 @@ class Func extends Event return $this; } - /** - * Returns set custom data for the function event. - * - * @return string - */ - public function getData(): string - { - return $this->data; - } - - /** - * Sets JWT for the function event. - * - * @param string $jwt - * @return self - */ - public function setJWT(string $jwt): self - { - $this->jwt = $jwt; - - return $this; - } - /** * Returns set JWT for the function event. * @@ -206,24 +182,15 @@ class Func extends Event } /** - * Executes the function event and sends it to the functions worker. + * Prepare payload for the function event. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - $events = $this->getEvent() ? Event::generateEvents($this->getEvent(), $this->getParams()) : null; - return $client->enqueue([ + return [ 'project' => $this->project, 'user' => $this->user, 'userId' => $this->userId, @@ -238,6 +205,6 @@ class Func extends Event 'path' => $this->path, 'headers' => $this->headers, 'method' => $this->method, - ]); + ]; } } diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index 0db576ba68..1c9e539cdb 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -2,7 +2,6 @@ namespace Appwrite\Event; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Mail extends Event @@ -397,22 +396,13 @@ class Mail extends Event } /** - * Executes the event and sends it to the mails worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'recipient' => $this->recipient, 'name' => $this->name, @@ -423,6 +413,6 @@ class Mail extends Event 'variables' => $this->variables, 'attachment' => $this->attachment, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); + ]; } } diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index ac2df7f92a..61dbe9c427 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Messaging extends Event @@ -176,21 +175,13 @@ class Messaging extends Event } /** - * Executes the event and sends it to the messaging worker. - * @return string|bool - * @throws \InvalidArgumentException + * Prepare the payload for the event + * + * @return array */ - public function trigger(): string | bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'type' => $this->type, 'project' => $this->project, 'user' => $this->user, @@ -198,6 +189,6 @@ class Messaging extends Event 'message' => $this->message, 'recipients' => $this->recipients, 'providerType' => $this->providerType, - ]); + ]; } } diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index 376264bce3..5fb2d5a106 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Migration extends Event @@ -68,25 +67,16 @@ class Migration extends Event } /** - * Executes the migration event and sends it to the migrations worker. + * Prepare the payload for the migration event. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'user' => $this->user, 'migration' => $this->migration, - ]); + ]; } } diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index f4f00b59d4..481c7918ca 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -43,6 +43,9 @@ class Realtime extends Event $collection = $this->getContext('collection'); $bucket = $this->getContext('bucket'); + // var_dump("-------------------- In Realtime trigger ---------------"); + // var_dump($this->getProject()); + $target = RealtimeAdapter::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php index f17c048a2e..5609859f37 100644 --- a/src/Appwrite/Event/Usage.php +++ b/src/Appwrite/Event/Usage.php @@ -3,7 +3,6 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class Usage extends Event @@ -51,6 +50,20 @@ class Usage extends Event return $this; } + /** + * Prepare the payload for the usage event. + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'project' => $this->project, + 'reduce' => $this->reduce, + 'metrics' => $this->metrics, + ]; + } + /** * Sends metrics to the usage worker. * @@ -58,22 +71,8 @@ class Usage extends Event */ public function trigger(): string|bool { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - $result = $client->enqueue([ - 'project' => $this->project, - 'reduce' => $this->reduce, - 'metrics' => $this->metrics, - ]); - + parent::trigger(); $this->metrics = []; - - return $result; + return true; } } diff --git a/src/Appwrite/Event/UsageDump.php b/src/Appwrite/Event/UsageDump.php index 83206e4add..6f44de4eda 100644 --- a/src/Appwrite/Event/UsageDump.php +++ b/src/Appwrite/Event/UsageDump.php @@ -2,7 +2,6 @@ namespace Appwrite\Event; -use Utopia\Queue\Client; use Utopia\Queue\Connection; class UsageDump extends Event @@ -32,22 +31,14 @@ class UsageDump extends Event } /** - * Sends metrics to the usage worker. + * Prepare the payload for the usage dump event. * - * @return string|bool + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $this->trimFields(); - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'stats' => $this->stats, - ]); + ]; } } diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 9d14dcdc3d..3e0dbe446f 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -15,10 +15,17 @@ class Webhook extends Event ->setClass(Event::WEBHOOK_CLASS_NAME); } - public function trigger(): string|bool + /** + * Trim the payload for the webhook event. + * + * @return array + */ + public function trimPayload(): array { - /** Filter out context and trim project to keep the payload small */ - $this->context = []; - return parent::trigger(); + $trimmed = parent::trimPayload(); + if (isset($this->context)) { + $trimmed['context'] = []; + } + return $trimmed; } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 9b9f03a100..d8d1eb8eb5 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -375,7 +375,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployment['headers']['status-code']); $this->assertEquals('ready', $deployment['body']['status']); - }, 500000, 1000); + }, 50000, 1000); $function = $this->getFunction($functionId); From a2962b6b95db0ec079cbfacf121a7895dd37c6f6 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 10:42:06 +0530 Subject: [PATCH 311/340] chore: review comments --- app/controllers/api/functions.php | 2 -- phpunit.xml | 2 +- src/Appwrite/Event/Event.php | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index f459875fca..f7606ed66b 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -402,8 +402,6 @@ App::post('/v1/functions') ]); - var_dump("-------------------- Create Function ---------------"); - var_dump($project); $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], diff --git a/phpunit.xml b/phpunit.xml index 598b730908..4c4e55ea4e 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > <extensions> <extension class="Appwrite\Tests\TestHook" /> diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 8dc0acbe2f..5cd5f8e7d6 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -344,6 +344,7 @@ class Event return false; } + /** The getter is required since events like Databases need to override the queue name depending on the project */ $client = new Client($this->getQueue(), $this->connection); // Merge the base payload with any trimmed values From f66f75b8085f537b745b47af5ae70ae765551388 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 10:43:02 +0530 Subject: [PATCH 312/340] chore: review comments --- app/controllers/api/functions.php | 1 - src/Appwrite/Event/Realtime.php | 3 --- 2 files changed, 4 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index f7606ed66b..efd6967408 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -401,7 +401,6 @@ App::post('/v1/functions') 'ruleId' => $rule->getId(), ]); - $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index 481c7918ca..f4f00b59d4 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -43,9 +43,6 @@ class Realtime extends Event $collection = $this->getContext('collection'); $bucket = $this->getContext('bucket'); - // var_dump("-------------------- In Realtime trigger ---------------"); - // var_dump($this->getProject()); - $target = RealtimeAdapter::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], From 455bc3370cf40a58c27e4a972920585a2923c2ad Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 11:16:21 +0530 Subject: [PATCH 313/340] chore: fix tests --- src/Appwrite/Event/Func.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 2e72cb86bf..b3945fccb8 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -181,6 +181,18 @@ class Func extends Event return $this->jwt; } + /** + * Sets JWT for the function event. + * + * @param string $jwt + * @return self + */ + public function setJWT(string $jwt): self + { + $this->jwt = $jwt; + return $this; + } + /** * Prepare payload for the function event. * From ef0b836987864e8ab167c88b3f4d34be9e6bea7b Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 11:19:34 +0530 Subject: [PATCH 314/340] chore: composer update --- composer.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.lock b/composer.lock index e60804b733..980dcdcd29 100644 --- a/composer.lock +++ b/composer.lock @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -3678,16 +3678,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.15", + "version": "0.33.16", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", + "url": "https://api.github.com/repos/utopia-php/http/zipball/e91d4c560d1b809e25faa63d564fef034363b50f", + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f", "shasum": "" }, "require": { @@ -3719,9 +3719,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.15" + "source": "https://github.com/utopia-php/http/tree/0.33.16" }, - "time": "2024-12-10T13:07:04+00:00" + "time": "2025-01-16T15:58:50+00:00" }, { "name": "utopia-php/image", @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.2", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2025-01-15T05:56:26+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", From 02e7f91e59c23725815b8c613902311a0c16b40a Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Fri, 17 Jan 2025 16:44:25 +0900 Subject: [PATCH 315/340] Address all missing descriptions apart from ones in projects.php --- app/controllers/api/account.php | 6 +++--- app/controllers/api/databases.php | 6 +++--- app/controllers/api/functions.php | 8 ++++---- app/controllers/api/project.php | 2 +- app/controllers/api/proxy.php | 2 +- app/controllers/api/storage.php | 4 ++-- app/controllers/api/users.php | 2 +- app/controllers/api/vcs.php | 16 ++++++++-------- docs/references/account/create-push-target.md | 1 + docs/references/account/delete-push-target.md | 1 + docs/references/account/update-push-target.md | 1 + .../references/databases/get-collection-usage.md | 1 + docs/references/databases/get-database-usage.md | 1 + docs/references/databases/get-usage.md | 1 + docs/references/functions/create-build.md | 1 + docs/references/functions/get-function-usage.md | 1 + docs/references/functions/get-functions-usage.md | 1 + .../functions/update-deployment-build.md | 1 + docs/references/project/get-usage.md | 1 + .../references/proxy/update-rule-verification.md | 1 + docs/references/storage/get-bucket-usage.md | 1 + docs/references/storage/get-usage.md | 1 + docs/references/users/get-usage.md | 1 + .../references/vcs/create-github-installation.md | 1 + .../vcs/create-repository-detection.md | 1 + docs/references/vcs/create-repository.md | 1 + docs/references/vcs/get-repository-contents.md | 1 + docs/references/vcs/get-repository.md | 1 + docs/references/vcs/list-repositories.md | 1 + docs/references/vcs/list-repository-branches.md | 1 + .../vcs/update-external-deployments.md | 1 + 31 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 docs/references/account/create-push-target.md create mode 100644 docs/references/account/delete-push-target.md create mode 100644 docs/references/account/update-push-target.md create mode 100644 docs/references/databases/get-collection-usage.md create mode 100644 docs/references/databases/get-database-usage.md create mode 100644 docs/references/databases/get-usage.md create mode 100644 docs/references/functions/create-build.md create mode 100644 docs/references/functions/get-function-usage.md create mode 100644 docs/references/functions/get-functions-usage.md create mode 100644 docs/references/functions/update-deployment-build.md create mode 100644 docs/references/project/get-usage.md create mode 100644 docs/references/proxy/update-rule-verification.md create mode 100644 docs/references/storage/get-bucket-usage.md create mode 100644 docs/references/storage/get-usage.md create mode 100644 docs/references/users/get-usage.md create mode 100644 docs/references/vcs/create-github-installation.md create mode 100644 docs/references/vcs/create-repository-detection.md create mode 100644 docs/references/vcs/create-repository.md create mode 100644 docs/references/vcs/get-repository-contents.md create mode 100644 docs/references/vcs/get-repository.md create mode 100644 docs/references/vcs/list-repositories.md create mode 100644 docs/references/vcs/list-repository-branches.md create mode 100644 docs/references/vcs/update-external-deployments.md diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 80c2b69ba3..bd9562110f 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4599,7 +4599,7 @@ App::post('/v1/account/targets/push') ->label('sdk', new Method( namespace: 'account', name: 'createPushTarget', - description: '', + description: '/docs/references/account/create-push-target.md', auth: [AuthType::SESSION], responses: [ new SDKResponse( @@ -4679,7 +4679,7 @@ App::put('/v1/account/targets/:targetId/push') ->label('sdk', new Method( namespace: 'account', name: 'updatePushTarget', - description: '', + description: '/docs/references/account/update-push-target.md', auth: [AuthType::SESSION], responses: [ new SDKResponse( @@ -4743,7 +4743,7 @@ App::delete('/v1/account/targets/:targetId/push') ->label('sdk', new Method( namespace: 'account', name: 'deletePushTarget', - description: '', + description: '/docs/references/account/delete-push-target.md', auth: [AuthType::SESSION], responses: [ new SDKResponse( diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4107614fa0..65a428c011 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4150,7 +4150,7 @@ App::get('/v1/databases/usage') ->label('sdk', new Method( namespace: 'databases', name: 'getUsage', - description: '', + description: '/docs/references/databases/get-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -4239,7 +4239,7 @@ App::get('/v1/databases/:databaseId/usage') ->label('sdk', new Method( namespace: 'databases', name: 'getDatabaseUsage', - description: '', + description: '/docs/references/databases/get-database-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -4334,7 +4334,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->label('sdk', new Method( namespace: 'databases', name: 'getCollectionUsage', - description: '', + description: '/docs/references/databases/get-collection-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 205f96072e..89d2444366 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -624,7 +624,7 @@ App::get('/v1/functions/:functionId/usage') ->label('sdk', new Method( namespace: 'functions', name: 'getFunctionUsage', - description: '', + description: '/docs/references/functions/get-function-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -735,7 +735,7 @@ App::get('/v1/functions/usage') ->label('sdk', new Method( namespace: 'functions', name: 'getUsage', - description: '', + description: '/docs/references/functions/get-functions-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1704,7 +1704,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/build') ->label('sdk', new Method( namespace: 'functions', name: 'createBuild', - description: '', + description: '/docs/references/functions/create-build.md', auth: [AuthType::KEY], responses: [ new SDKResponse( @@ -1779,7 +1779,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build') ->label('sdk', new Method( namespace: 'functions', name: 'updateDeploymentBuild', - description: '', + description: '/docs/references/functions/update-deployment-build.md', auth: [AuthType::KEY], responses: [ new SDKResponse( diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 2fc6578c2b..cde2b150f7 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -27,7 +27,7 @@ App::get('/v1/project/usage') ->label('sdk', new Method( namespace: 'project', name: 'getUsage', - description: '', + description: '/docs/references/project/get-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index ef39ed0ab6..2567c23be6 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -327,7 +327,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->label('sdk', new Method( namespace: 'proxy', name: 'updateRuleVerification', - description: '', + description: '/docs/references/proxy/update-rule-verification.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 49f8897884..b6a07c356d 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1774,7 +1774,7 @@ App::get('/v1/storage/usage') ->label('sdk', new Method( namespace: 'storage', name: 'getUsage', - description: '', + description: '/docs/references/storage/get-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1860,7 +1860,7 @@ App::get('/v1/storage/:bucketId/usage') ->label('sdk', new Method( namespace: 'storage', name: 'getBucketUsage', - description: '', + description: '/docs/references/storage/get-bucket-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d2c840d368..962022927f 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2391,7 +2391,7 @@ App::get('/v1/users/usage') ->label('sdk', new Method( namespace: 'users', name: 'getUsage', - description: '', + description: '/docs/references/users/get-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 7c31d93df5..2c145febcc 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -276,7 +276,7 @@ App::get('/v1/vcs/github/authorize') ->label('sdk', new Method( namespace: 'vcs', name: 'createGitHubInstallation', - description: '', + description: '/docs/references/vcs/create-github-installation.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -457,7 +457,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->label('sdk', new Method( namespace: 'vcs', name: 'getRepositoryContents', - description: '', + description: '/docs/references/vcs/get-repository-contents.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -523,7 +523,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr ->label('sdk', new Method( namespace: 'vcs', name: 'createRepositoryDetection', - description: '', + description: '/docs/references/vcs/create-repository-detection.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -600,7 +600,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->label('sdk', new Method( namespace: 'vcs', name: 'listRepositories', - description: '', + description: '/docs/references/vcs/list-repositories.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -700,7 +700,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->label('sdk', new Method( namespace: 'vcs', name: 'createRepository', - description: '', + description: '/docs/references/vcs/create-repository.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -812,7 +812,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->label('sdk', new Method( namespace: 'vcs', name: 'getRepository', - description: '', + description: '/docs/references/vcs/get-repository.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -866,7 +866,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->label('sdk', new Method( namespace: 'vcs', name: 'listRepositoryBranches', - description: '', + description: '/docs/references/vcs/list-repository-branches.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1204,7 +1204,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->label('sdk', new Method( namespace: 'vcs', name: 'updateExternalDeployments', - description: '', + description: '/docs/references/vcs/update-external-deployments.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/docs/references/account/create-push-target.md b/docs/references/account/create-push-target.md new file mode 100644 index 0000000000..c54f180638 --- /dev/null +++ b/docs/references/account/create-push-target.md @@ -0,0 +1 @@ +Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model. \ No newline at end of file diff --git a/docs/references/account/delete-push-target.md b/docs/references/account/delete-push-target.md new file mode 100644 index 0000000000..5909a37b27 --- /dev/null +++ b/docs/references/account/delete-push-target.md @@ -0,0 +1 @@ +Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user. \ No newline at end of file diff --git a/docs/references/account/update-push-target.md b/docs/references/account/update-push-target.md new file mode 100644 index 0000000000..997ffaafea --- /dev/null +++ b/docs/references/account/update-push-target.md @@ -0,0 +1 @@ +Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead. \ No newline at end of file diff --git a/docs/references/databases/get-collection-usage.md b/docs/references/databases/get-collection-usage.md new file mode 100644 index 0000000000..48682a075f --- /dev/null +++ b/docs/references/databases/get-collection-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. \ No newline at end of file diff --git a/docs/references/databases/get-database-usage.md b/docs/references/databases/get-database-usage.md new file mode 100644 index 0000000000..2c2628a464 --- /dev/null +++ b/docs/references/databases/get-database-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. \ No newline at end of file diff --git a/docs/references/databases/get-usage.md b/docs/references/databases/get-usage.md new file mode 100644 index 0000000000..d41f8704c8 --- /dev/null +++ b/docs/references/databases/get-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. \ No newline at end of file diff --git a/docs/references/functions/create-build.md b/docs/references/functions/create-build.md new file mode 100644 index 0000000000..7a8ac750e8 --- /dev/null +++ b/docs/references/functions/create-build.md @@ -0,0 +1 @@ +Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build. \ No newline at end of file diff --git a/docs/references/functions/get-function-usage.md b/docs/references/functions/get-function-usage.md new file mode 100644 index 0000000000..4498abb05b --- /dev/null +++ b/docs/references/functions/get-function-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days. \ No newline at end of file diff --git a/docs/references/functions/get-functions-usage.md b/docs/references/functions/get-functions-usage.md new file mode 100644 index 0000000000..14427d335d --- /dev/null +++ b/docs/references/functions/get-functions-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for a for all functions. View statistics including total functions, deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days. \ No newline at end of file diff --git a/docs/references/functions/update-deployment-build.md b/docs/references/functions/update-deployment-build.md new file mode 100644 index 0000000000..d047990adf --- /dev/null +++ b/docs/references/functions/update-deployment-build.md @@ -0,0 +1 @@ +Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details. \ No newline at end of file diff --git a/docs/references/project/get-usage.md b/docs/references/project/get-usage.md new file mode 100644 index 0000000000..d6802c5588 --- /dev/null +++ b/docs/references/project/get-usage.md @@ -0,0 +1 @@ +Get comprehensive usage statistics for your project. View metrics including network requests, bandwidth, storage, function executions, database usage, and user activity. Specify a time range with startDate and endDate, and optionally set the data granularity with period (1h or 1d). The response includes both total counts and detailed breakdowns by resource, along with historical data over the specified period. \ No newline at end of file diff --git a/docs/references/proxy/update-rule-verification.md b/docs/references/proxy/update-rule-verification.md new file mode 100644 index 0000000000..c06994bc59 --- /dev/null +++ b/docs/references/proxy/update-rule-verification.md @@ -0,0 +1 @@ +Retry getting verification process of a proxy rule. This endpoint triggers domain verification by checking DNS records (CNAME) against the configured target domain. If verification is successful, a TLS certificate will be automatically provisioned for the domain. \ No newline at end of file diff --git a/docs/references/storage/get-bucket-usage.md b/docs/references/storage/get-bucket-usage.md new file mode 100644 index 0000000000..98e9867831 --- /dev/null +++ b/docs/references/storage/get-bucket-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics a specific bucket in the project. You can view the total number of files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. diff --git a/docs/references/storage/get-usage.md b/docs/references/storage/get-usage.md new file mode 100644 index 0000000000..697c680001 --- /dev/null +++ b/docs/references/storage/get-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for all buckets in the project. You can view the total number of buckets, files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. diff --git a/docs/references/users/get-usage.md b/docs/references/users/get-usage.md new file mode 100644 index 0000000000..2a9379c847 --- /dev/null +++ b/docs/references/users/get-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for all users in the project. You can view the total number of users and sessions. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days. diff --git a/docs/references/vcs/create-github-installation.md b/docs/references/vcs/create-github-installation.md new file mode 100644 index 0000000000..60873faf6d --- /dev/null +++ b/docs/references/vcs/create-github-installation.md @@ -0,0 +1 @@ +Begin Appwrite's GitHub's app installation to set up version control integration. This endpoint responds with a redirect URL to the GitHub App's installation page. The GitHub App must be configured in your environment for this endpoint to work. \ No newline at end of file diff --git a/docs/references/vcs/create-repository-detection.md b/docs/references/vcs/create-repository-detection.md new file mode 100644 index 0000000000..d031cdc746 --- /dev/null +++ b/docs/references/vcs/create-repository-detection.md @@ -0,0 +1 @@ +Analyze a GitHub repository to automatically detect the programming language and runtime environment. This endpoint scans the repository's files and language statistics to determine the appropriate runtime settings for your function. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work. \ No newline at end of file diff --git a/docs/references/vcs/create-repository.md b/docs/references/vcs/create-repository.md new file mode 100644 index 0000000000..771265bd01 --- /dev/null +++ b/docs/references/vcs/create-repository.md @@ -0,0 +1 @@ +Create a new GitHub repository through your installation. This endpoint allows you to create either a public or private repository by specifying a name and visibility setting. The repository will be created under your GitHub user account or organization, depending on your installation type. The GitHub installation must be properly configured and have the necessary permissions for repository creation. \ No newline at end of file diff --git a/docs/references/vcs/get-repository-contents.md b/docs/references/vcs/get-repository-contents.md new file mode 100644 index 0000000000..ab5ef7f8da --- /dev/null +++ b/docs/references/vcs/get-repository-contents.md @@ -0,0 +1 @@ +Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work. diff --git a/docs/references/vcs/get-repository.md b/docs/references/vcs/get-repository.md new file mode 100644 index 0000000000..ee57861114 --- /dev/null +++ b/docs/references/vcs/get-repository.md @@ -0,0 +1 @@ +Get detailed information about a specific GitHub repository from your installation. This endpoint returns repository details including its ID, name, visibility status, organization, and latest push date. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work. \ No newline at end of file diff --git a/docs/references/vcs/list-repositories.md b/docs/references/vcs/list-repositories.md new file mode 100644 index 0000000000..f486e9b584 --- /dev/null +++ b/docs/references/vcs/list-repositories.md @@ -0,0 +1 @@ +Get a list of GitHub repositories available through your installation. This endpoint returns repositories with their basic information, detected runtime environments, and latest push dates. You can optionally filter repositories using a search term. Each repository's runtime is automatically detected based on its contents and language statistics. The GitHub installation must be properly configured for this endpoint to work. \ No newline at end of file diff --git a/docs/references/vcs/list-repository-branches.md b/docs/references/vcs/list-repository-branches.md new file mode 100644 index 0000000000..eea1795a3e --- /dev/null +++ b/docs/references/vcs/list-repository-branches.md @@ -0,0 +1 @@ +Get a list of all branches from a GitHub repository in your installation. This endpoint returns the names of all branches in the repository and their total count. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work. diff --git a/docs/references/vcs/update-external-deployments.md b/docs/references/vcs/update-external-deployments.md new file mode 100644 index 0000000000..22d95da9a7 --- /dev/null +++ b/docs/references/vcs/update-external-deployments.md @@ -0,0 +1 @@ +Authorize and create deployments for a GitHub pull request in your project. This endpoint allows external contributions by creating deployments from pull requests, enabling preview environments for code review. The pull request must be open and not previously authorized. The GitHub installation must be properly configured and have access to both the repository and pull request for this endpoint to work. \ No newline at end of file From e343a1068eca9322a1fc6df7c1b50a8d8b7807d8 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:55:14 +0000 Subject: [PATCH 316/340] fix: linter --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index f89889f534..980dcdcd29 100644 --- a/composer.lock +++ b/composer.lock @@ -4095,16 +4095,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.2", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf" + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6f9243848f1c6466f6509fd01c7e18306a6d8caf", - "reference": "6f9243848f1c6466f6509fd01c7e18306a6d8caf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", + "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", "shasum": "" }, "require": { @@ -4139,9 +4139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.1" }, - "time": "2025-01-15T05:56:26+00:00" + "time": "2024-10-22T10:27:49+00:00" }, { "name": "utopia-php/pools", From 40f16fab500e0941be5ef21eb4a2a9abb4643a77 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 17 Jan 2025 10:17:49 +0000 Subject: [PATCH 317/340] docs: add compression vars to documentation --- app/config/variables.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/config/variables.php b/app/config/variables.php index 113fbae335..57810525c7 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -268,6 +268,24 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPRESSION_ENABLED', + 'description' => 'This option allows you to enable or disable the response compression for the Appwrite API. It\'s enabled by default with value "enabled", and to disable it, pass value "disabled".', + 'introduction' => '1.6.0', + 'default' => 'enabled', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_COMPRESSION_MIN_SIZE_BYTES', + 'description' => 'This option allows you to set the minimum size in bytes for the response compression to be applied. The default value is 1024 bytes.', + 'introduction' => '1.6.0', + 'default' => 1024, + 'required' => false, + 'question' => '', + 'filter' => '' + ] ], ], [ From 5b28e7c478fe4630cf82e3c0e7d8aef2db7acdb4 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 11:48:19 +0000 Subject: [PATCH 318/340] chore: review comments --- app/controllers/shared/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 592c7b8a49..2f094e33ef 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -76,7 +76,7 @@ $eventDatabaseListener = function (Document $project, Document $document, Respon /** Trigger webhooks events only if a project has them enabled */ - if ($project->getAttribute('webhooks', []) !== []) { + if (!empty($project->getAttribute('webhooks'))) { $queueForWebhooks ->from($queueForEvents) ->trigger(); @@ -697,7 +697,7 @@ App::shutdown() * But it might have performance implications on the API due to the number of webhooks etc. * Some profiling is needed to see if this is a problem. */ - if ($project->getAttribute('webhooks', []) !== []) { + if (!empty($project->getAttribute('webhooks'))) { $queueForWebhooks ->from($queueForEvents) ->trigger(); From e4efaf1efa36ac2aa8cd3754e9cca29aecaa2d4d Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 22:53:31 +0530 Subject: [PATCH 319/340] fix: maintenance job missing type --- .env | 2 +- src/Appwrite/Platform/Tasks/Maintenance.php | 17 +++++------------ src/Appwrite/Platform/Workers/Deletes.php | 3 +++ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.env b/.env index 8f7d7996e7..53a93b5fb2 100644 --- a/.env +++ b/.env @@ -79,7 +79,7 @@ _APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes _APP_EXECUTOR_SECRET=your-secret-key _APP_EXECUTOR_HOST=http://proxy/v1 _APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1 -_APP_MAINTENANCE_INTERVAL=86400 +_APP_MAINTENANCE_INTERVAL=60 _APP_MAINTENANCE_DELAY= _APP_MAINTENANCE_RETENTION_CACHE=2592000 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index a7558934b5..2d37bdbf70 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -47,9 +47,12 @@ class Maintenance extends Action Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); $this->foreachProject($dbForPlatform, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { - $queueForDeletes->setProject($project); + $queueForDeletes + ->setType(DELETE_TYPE_MAINTENANCE) + ->setProject($project) + ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->trigger(); - $this->notifyProjects($queueForDeletes, $usageStatsRetentionHourly); }); $this->notifyDeleteConnections($queueForDeletes); @@ -59,16 +62,6 @@ class Maintenance extends Action }, $interval, $delay); } - /** - * Hook to allow sub-classes to extend project-level maintenance functionality. - */ - protected function notifyProjects(Delete $queueForDeletes, int $usageStatsRetentionHourly): void - { - $queueForDeletes - ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) - ->trigger(); - } - protected function foreachProject(Database $dbForPlatform, callable $callback): void { // TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 539bbd61f9..dcfbd1d1e7 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -83,6 +83,9 @@ class Deletes extends Action $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); + var_dump("--------------------------------"); + var_dump($type); + switch (\strval($type)) { case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { From e7d33ebc5258b42530f4c49ca03e7bbdc6cd9324 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 22:55:00 +0530 Subject: [PATCH 320/340] fix: maintenance job missing type --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 53a93b5fb2..8f7d7996e7 100644 --- a/.env +++ b/.env @@ -79,7 +79,7 @@ _APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes _APP_EXECUTOR_SECRET=your-secret-key _APP_EXECUTOR_HOST=http://proxy/v1 _APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1 -_APP_MAINTENANCE_INTERVAL=60 +_APP_MAINTENANCE_INTERVAL=86400 _APP_MAINTENANCE_DELAY= _APP_MAINTENANCE_RETENTION_CACHE=2592000 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 From dc651f632af6358b5085101603a522d7d5861098 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Fri, 17 Jan 2025 22:55:16 +0530 Subject: [PATCH 321/340] fix: maintenance job missing type --- src/Appwrite/Platform/Workers/Deletes.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index dcfbd1d1e7..539bbd61f9 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -83,9 +83,6 @@ class Deletes extends Action $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); - var_dump("--------------------------------"); - var_dump($type); - switch (\strval($type)) { case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { From 1d1b83afb6f46403a45e256a56910a172bb9ad39 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Fri, 17 Jan 2025 17:27:54 +0000 Subject: [PATCH 322/340] chore: review --- app/controllers/api/teams.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 7efe2a5a2d..d98cfe6f0b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -582,11 +582,12 @@ App::post('/v1/teams/:teamId/memberships') Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } else { - $membership = new Document([ - '$id' => $membership->getId(), - 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, - 'confirm' => ($isPrivilegedUser || $isAppUser), - ]); + $membership->setAttribute('invited', DateTime::now()); + + if ($isPrivilegedUser || $isAppUser) { + $membership->setAttribute('joined', DateTime::now()); + $membership->setAttribute('confirm', true); + } $membership = ($isPrivilegedUser || $isAppUser) ? Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : From 733434fdb8e582130d7c895e66a49638a42df488 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Sun, 19 Jan 2025 08:18:22 +0200 Subject: [PATCH 323/340] formatOptions default --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index 954e29410d..ba775956bd 100644 --- a/app/init.php +++ b/app/init.php @@ -769,7 +769,7 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () { }, Database::VAR_DATETIME); Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { - $elements = $attribute['formatOptions']['elements']; + $elements = $attribute['formatOptions']['elements'] ?? []; return new WhiteList($elements, true); }, Database::VAR_STRING); From fba5060469850273803c925c3a19ab5628a3f106 Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Sun, 19 Jan 2025 08:30:02 +0200 Subject: [PATCH 324/340] Bumb version --- composer.json | 6 ++-- composer.lock | 92 +++++++++++++++++++++++++-------------------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/composer.json b/composer.json index 4e1b5a98a2..0060e2727f 100644 --- a/composer.json +++ b/composer.json @@ -45,13 +45,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.46.*", + "utopia-php/abuse": "0.47.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.46.*", + "utopia-php/audit": "0.47.*", "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.32", + "utopia-php/database": "0.56.3", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 68dbc191bf..a5fafe51ea 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": "3853435a659889e86c16764046950bed", + "content-hash": "8577c89ac09e39dfd8d0c53afe6787bc", "packages": [ { "name": "adhocore/jwt", @@ -1430,16 +1430,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d" + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/66c3b98e998a726691c92e6405a82e6e7b8b169d", - "reference": "66c3b98e998a726691c92e6405a82e6e7b8b169d", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-30T11:49:49+00:00" + "time": "2025-01-15T23:07:07+00:00" }, { "name": "open-telemetry/sdk", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.46.2", + "version": "0.47.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "59749df988430b28953fb5cabfad88b0ff5b539b" + "reference": "2b52bb362234d4072b647ed57db1b3be030f57c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/59749df988430b28953fb5cabfad88b0ff5b539b", - "reference": "59749df988430b28953fb5cabfad88b0ff5b539b", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/2b52bb362234d4072b647ed57db1b3be030f57c2", + "reference": "2b52bb362234d4072b647ed57db1b3be030f57c2", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.32" + "utopia-php/database": "0.56.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.46.2" + "source": "https://github.com/utopia-php/abuse/tree/0.47.0" }, - "time": "2025-01-13T02:09:43+00:00" + "time": "2025-01-15T02:41:02+00:00" }, { "name": "utopia-php/analytics", @@ -3233,21 +3233,21 @@ }, { "name": "utopia-php/audit", - "version": "0.46.1", + "version": "0.47.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37" + "reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/21255fa1ce66433140a43d380b2859c7f0a0bb37", - "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1ebd5784ba68645073426f2f04a67726a1bde4d7", + "reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.53.32" + "utopia-php/database": "0.56.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3274,9 +3274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.46.1" + "source": "https://github.com/utopia-php/audit/tree/0.47.0" }, - "time": "2025-01-13T02:19:56+00:00" + "time": "2025-01-15T02:40:53+00:00" }, { "name": "utopia-php/cache", @@ -3379,16 +3379,16 @@ }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -3419,9 +3419,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.32", + "version": "0.56.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "981a1241139b42dccd531511130b79137740b205" + "reference": "b53f7018fd9c9feff4e2235a0011f2f48609f19c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205", - "reference": "981a1241139b42dccd531511130b79137740b205", + "url": "https://api.github.com/repos/utopia-php/database/zipball/b53f7018fd9c9feff4e2235a0011f2f48609f19c", + "reference": "b53f7018fd9c9feff4e2235a0011f2f48609f19c", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.32" + "source": "https://github.com/utopia-php/database/tree/0.56.3" }, - "time": "2025-01-10T08:53:47+00:00" + "time": "2025-01-17T04:04:20+00:00" }, { "name": "utopia-php/domains", @@ -3678,16 +3678,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.15", + "version": "0.33.16", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", - "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", + "url": "https://api.github.com/repos/utopia-php/http/zipball/e91d4c560d1b809e25faa63d564fef034363b50f", + "reference": "e91d4c560d1b809e25faa63d564fef034363b50f", "shasum": "" }, "require": { @@ -3719,9 +3719,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.15" + "source": "https://github.com/utopia-php/http/tree/0.33.16" }, - "time": "2024-12-10T13:07:04+00:00" + "time": "2025-01-16T15:58:50+00:00" }, { "name": "utopia-php/image", @@ -3929,16 +3929,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.14", + "version": "0.6.15", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2" + "reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/e849ec3e7ad38f5f5273ebb0132b112639cdf01c", + "reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c", "shasum": "" }, "require": { @@ -3946,7 +3946,7 @@ "ext-curl": "*", "ext-openssl": "*", "php": "8.3.*", - "utopia-php/database": "0.53.*", + "utopia-php/database": "0.56.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" @@ -3979,9 +3979,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.14" + "source": "https://github.com/utopia-php/migration/tree/0.6.15" }, - "time": "2025-01-08T01:07:25+00:00" + "time": "2025-01-15T04:55:08+00:00" }, { "name": "utopia-php/mongo", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 0408de32535e9aa226e0ff8bdde4097eec4cd685 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Mon, 20 Jan 2025 02:14:29 +0000 Subject: [PATCH 325/340] Update Fetch to 0.3.0 --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 4e1b5a98a2..1cdbe5053c 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", - "utopia-php/fetch": "0.2.*", + "utopia-php/fetch": "0.3.*", "utopia-php/image": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", diff --git a/composer.lock b/composer.lock index 980dcdcd29..dea3ad41f6 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": "3853435a659889e86c16764046950bed", + "content-hash": "92b40e75d531c98b72508dd104eeab0d", "packages": [ { "name": "adhocore/jwt", @@ -3639,16 +3639,16 @@ }, { "name": "utopia-php/fetch", - "version": "0.2.1", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/utopia-php/fetch.git", - "reference": "1423c0ee3eef944d816ca6e31706895b585aea82" + "reference": "02b12c05aec13399dcc2da8d51f908e328ab63f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/fetch/zipball/1423c0ee3eef944d816ca6e31706895b585aea82", - "reference": "1423c0ee3eef944d816ca6e31706895b585aea82", + "url": "https://api.github.com/repos/utopia-php/fetch/zipball/02b12c05aec13399dcc2da8d51f908e328ab63f4", + "reference": "02b12c05aec13399dcc2da8d51f908e328ab63f4", "shasum": "" }, "require": { @@ -3672,9 +3672,9 @@ "description": "A simple library that provides an interface for making HTTP Requests.", "support": { "issues": "https://github.com/utopia-php/fetch/issues", - "source": "https://github.com/utopia-php/fetch/tree/0.2.1" + "source": "https://github.com/utopia-php/fetch/tree/0.3.0" }, - "time": "2024-03-18T11:50:59+00:00" + "time": "2025-01-17T06:11:10+00:00" }, { "name": "utopia-php/framework", From f3b395f3f3a0d1ad10a73931354881f182b34396 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Mon, 20 Jan 2025 12:16:00 +0900 Subject: [PATCH 326/340] Add remaining missing descriptions and enable the desc check --- app/config/specs/open-api3-latest-client.json | 12 +- .../specs/open-api3-latest-console.json | 304 +++++++++--------- app/config/specs/open-api3-latest-server.json | 8 +- app/config/specs/swagger2-latest-client.json | 12 +- app/config/specs/swagger2-latest-console.json | 304 +++++++++--------- app/config/specs/swagger2-latest-server.json | 8 +- app/controllers/api/projects.php | 92 +++--- docs/references/assistant/chat.md | 1 + .../references/migrations/delete-migration.md | 1 + docs/references/migrations/get-migration.md | 1 + docs/references/migrations/list-migrations.md | 1 + .../migrations/migration-appwrite-report.md | 1 + .../migrations/migration-appwrite.md | 1 + .../migrations/migration-firebase-report.md | 1 + .../migrations/migration-firebase.md | 1 + .../migrations/migration-nhost-report.md | 1 + docs/references/migrations/migration-nhost.md | 1 + .../migrations/migration-supabase-report.md | 1 + .../migrations/migration-supabase.md | 1 + docs/references/migrations/retry-migration.md | 1 + docs/references/projects/create-jwt.md | 1 + docs/references/projects/create-key.md | 1 + docs/references/projects/create-platform.md | 1 + docs/references/projects/create-smtp-test.md | 1 + docs/references/projects/create-webhook.md | 1 + docs/references/projects/create.md | 1 + .../projects/delete-email-template.md | 1 + docs/references/projects/delete-key.md | 1 + docs/references/projects/delete-platform.md | 1 + .../projects/delete-sms-template.md | 1 + docs/references/projects/delete-webhook.md | 1 + docs/references/projects/delete.md | 1 + .../references/projects/get-email-template.md | 1 + docs/references/projects/get-key.md | 1 + docs/references/projects/get-platform.md | 1 + docs/references/projects/get-sms-template.md | 1 + docs/references/projects/get-webhook.md | 1 + docs/references/projects/get.md | 1 + docs/references/projects/list-keys.md | 1 + docs/references/projects/list-platforms.md | 1 + docs/references/projects/list-webhooks.md | 1 + docs/references/projects/list.md | 1 + .../projects/update-api-status-all.md | 1 + docs/references/projects/update-api-status.md | 1 + .../projects/update-auth-duration.md | 1 + docs/references/projects/update-auth-limit.md | 1 + .../update-auth-password-dictionary.md | 1 + .../projects/update-auth-password-history.md | 1 + .../projects/update-auth-sessions-limit.md | 1 + .../references/projects/update-auth-status.md | 1 + .../projects/update-email-template.md | 1 + docs/references/projects/update-key.md | 1 + .../projects/update-memberships-privacy.md | 1 + .../projects/update-mock-numbers.md | 1 + docs/references/projects/update-oauth2.md | 1 + .../projects/update-personal-data-check.md | 1 + docs/references/projects/update-platform.md | 1 + .../projects/update-service-status-all.md | 1 + .../projects/update-service-status.md | 1 + .../projects/update-session-alerts.md | 1 + .../projects/update-sms-template.md | 1 + docs/references/projects/update-smtp.md | 1 + docs/references/projects/update-team.md | 1 + .../projects/update-webhook-signature.md | 1 + docs/references/projects/update-webhook.md | 1 + docs/references/projects/update.md | 1 + docs/references/vcs/delete-installation.md | 1 + docs/references/vcs/get-installation.md | 1 + docs/references/vcs/list-installations.md | 1 + src/Appwrite/SDK/Method.php | 2 +- 70 files changed, 433 insertions(+), 371 deletions(-) create mode 100644 docs/references/assistant/chat.md create mode 100644 docs/references/migrations/delete-migration.md create mode 100644 docs/references/migrations/get-migration.md create mode 100644 docs/references/migrations/list-migrations.md create mode 100644 docs/references/migrations/migration-appwrite-report.md create mode 100644 docs/references/migrations/migration-appwrite.md create mode 100644 docs/references/migrations/migration-firebase-report.md create mode 100644 docs/references/migrations/migration-firebase.md create mode 100644 docs/references/migrations/migration-nhost-report.md create mode 100644 docs/references/migrations/migration-nhost.md create mode 100644 docs/references/migrations/migration-supabase-report.md create mode 100644 docs/references/migrations/migration-supabase.md create mode 100644 docs/references/migrations/retry-migration.md create mode 100644 docs/references/projects/create-jwt.md create mode 100644 docs/references/projects/create-key.md create mode 100644 docs/references/projects/create-platform.md create mode 100644 docs/references/projects/create-smtp-test.md create mode 100644 docs/references/projects/create-webhook.md create mode 100644 docs/references/projects/create.md create mode 100644 docs/references/projects/delete-email-template.md create mode 100644 docs/references/projects/delete-key.md create mode 100644 docs/references/projects/delete-platform.md create mode 100644 docs/references/projects/delete-sms-template.md create mode 100644 docs/references/projects/delete-webhook.md create mode 100644 docs/references/projects/delete.md create mode 100644 docs/references/projects/get-email-template.md create mode 100644 docs/references/projects/get-key.md create mode 100644 docs/references/projects/get-platform.md create mode 100644 docs/references/projects/get-sms-template.md create mode 100644 docs/references/projects/get-webhook.md create mode 100644 docs/references/projects/get.md create mode 100644 docs/references/projects/list-keys.md create mode 100644 docs/references/projects/list-platforms.md create mode 100644 docs/references/projects/list-webhooks.md create mode 100644 docs/references/projects/list.md create mode 100644 docs/references/projects/update-api-status-all.md create mode 100644 docs/references/projects/update-api-status.md create mode 100644 docs/references/projects/update-auth-duration.md create mode 100644 docs/references/projects/update-auth-limit.md create mode 100644 docs/references/projects/update-auth-password-dictionary.md create mode 100644 docs/references/projects/update-auth-password-history.md create mode 100644 docs/references/projects/update-auth-sessions-limit.md create mode 100644 docs/references/projects/update-auth-status.md create mode 100644 docs/references/projects/update-email-template.md create mode 100644 docs/references/projects/update-key.md create mode 100644 docs/references/projects/update-memberships-privacy.md create mode 100644 docs/references/projects/update-mock-numbers.md create mode 100644 docs/references/projects/update-oauth2.md create mode 100644 docs/references/projects/update-personal-data-check.md create mode 100644 docs/references/projects/update-platform.md create mode 100644 docs/references/projects/update-service-status-all.md create mode 100644 docs/references/projects/update-service-status.md create mode 100644 docs/references/projects/update-session-alerts.md create mode 100644 docs/references/projects/update-sms-template.md create mode 100644 docs/references/projects/update-smtp.md create mode 100644 docs/references/projects/update-team.md create mode 100644 docs/references/projects/update-webhook-signature.md create mode 100644 docs/references/projects/update-webhook.md create mode 100644 docs/references/projects/update.md create mode 100644 docs/references/vcs/delete-installation.md create mode 100644 docs/references/vcs/get-installation.md create mode 100644 docs/references/vcs/list-installations.md diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 4c82afc8a7..232861f0ff 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -2371,7 +2371,7 @@ "tags": [ "account" ], - "description": "", + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", "responses": { "201": { "description": "Target", @@ -2391,7 +2391,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2449,7 +2449,7 @@ "tags": [ "account" ], - "description": "", + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", "responses": { "200": { "description": "Target", @@ -2469,7 +2469,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2526,7 +2526,7 @@ "tags": [ "account" ], - "description": "", + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", "responses": { "204": { "description": "No content" @@ -2539,7 +2539,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index fa0455e2ee..42ed7b9d28 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -2382,7 +2382,7 @@ "tags": [ "account" ], - "description": "", + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", "responses": { "201": { "description": "Target", @@ -2402,7 +2402,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2459,7 +2459,7 @@ "tags": [ "account" ], - "description": "", + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", "responses": { "200": { "description": "Target", @@ -2479,7 +2479,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2535,7 +2535,7 @@ "tags": [ "account" ], - "description": "", + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", "responses": { "204": { "description": "No content" @@ -2548,7 +2548,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -4285,7 +4285,7 @@ "tags": [ "assistant" ], - "description": "", + "description": "Send a prompt to the AI assistant and receive a response. This endpoint allows you to interact with Appwrite's AI assistant by sending questions or prompts and receiving helpful responses in real-time through a server-sent events stream. ", "responses": { "200": { "description": "File" @@ -4541,7 +4541,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageDatabases", @@ -4561,7 +4561,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -8727,7 +8727,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageCollection", @@ -8747,7 +8747,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -8890,7 +8890,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageDatabase", @@ -8910,7 +8910,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-database-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9544,7 +9544,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for all functions. View statistics including total functions, deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunctions", @@ -9564,7 +9564,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-functions-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10332,7 +10332,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "204": { "description": "No content" @@ -10345,7 +10345,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10409,7 +10409,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Build", @@ -10429,7 +10429,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10877,7 +10877,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunction", @@ -10897,7 +10897,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -17482,7 +17482,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "List all migrations in the current project. This endpoint returns a list of all migrations including their status, progress, and any errors that occurred during the migration process.", "responses": { "200": { "description": "Migrations List", @@ -17555,7 +17555,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from another Appwrite project to your current project. This endpoint allows you to migrate resources like databases, collections, documents, users, and files from an existing Appwrite project. ", "responses": { "202": { "description": "Migration", @@ -17642,7 +17642,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in an Appwrite project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", "responses": { "200": { "description": "Migration Report", @@ -17734,7 +17734,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from a Firebase project to your Appwrite project. This endpoint allows you to migrate resources like authentication and other supported services from a Firebase project. ", "responses": { "202": { "description": "Migration", @@ -17809,7 +17809,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in a Firebase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", "responses": { "200": { "description": "Migration Report", @@ -17880,7 +17880,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from an NHost project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from an NHost project. ", "responses": { "202": { "description": "Migration", @@ -17990,7 +17990,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a detailed report of the data in an NHost project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", "responses": { "200": { "description": "Migration Report", @@ -18122,7 +18122,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from a Supabase project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from a Supabase project. ", "responses": { "202": { "description": "Migration", @@ -18226,7 +18226,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in a Supabase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", "responses": { "200": { "description": "Migration Report", @@ -18349,7 +18349,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Get a migration by its unique ID. This endpoint returns detailed information about a specific migration including its current status, progress, and any errors that occurred during the migration process. ", "responses": { "200": { "description": "Migration", @@ -18406,7 +18406,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -18463,7 +18463,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. ", "responses": { "204": { "description": "No content" @@ -18515,7 +18515,7 @@ "tags": [ "project" ], - "description": "", + "description": "Get comprehensive usage statistics for your project. View metrics including network requests, bandwidth, storage, function executions, database usage, and user activity. Specify a time range with startDate and endDate, and optionally set the data granularity with period (1h or 1d). The response includes both total counts and detailed breakdowns by resource, along with historical data over the specified period.", "responses": { "200": { "description": "UsageProject", @@ -18535,7 +18535,7 @@ "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -18909,7 +18909,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -18929,7 +18929,7 @@ "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -18980,7 +18980,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -19000,7 +19000,7 @@ "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19114,7 +19114,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a project by its unique ID. This endpoint allows you to retrieve the project's details, including its name, description, team, region, and other metadata. ", "responses": { "200": { "description": "Project", @@ -19134,7 +19134,7 @@ "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19171,7 +19171,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -19191,7 +19191,7 @@ "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19292,7 +19292,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -19305,7 +19305,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19344,7 +19344,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime.", "responses": { "200": { "description": "Project", @@ -19364,7 +19364,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19435,7 +19435,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all API types. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime all at once.", "responses": { "200": { "description": "Project", @@ -19455,7 +19455,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status-all.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19513,7 +19513,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -19533,7 +19533,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-duration.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19591,7 +19591,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -19611,7 +19611,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-limit.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19669,7 +19669,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of sessions allowed per user within the project, if the limit is hit the oldest session will be deleted to make room for new sessions.", "responses": { "200": { "description": "Project", @@ -19689,7 +19689,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-sessions-limit.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19747,7 +19747,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update project membership privacy settings. Use this endpoint to control what user information is visible to other team members, such as user name, email, and MFA status. ", "responses": { "200": { "description": "Project", @@ -19767,7 +19767,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-memberships-privacy.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19837,7 +19837,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -19857,7 +19857,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-mock-numbers.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19918,7 +19918,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. ", "responses": { "200": { "description": "Project", @@ -19938,7 +19938,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-dictionary.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19996,7 +19996,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the authentication password history requirement. Use this endpoint to require new passwords to be different than the last X amount of previously used ones.", "responses": { "200": { "description": "Project", @@ -20016,7 +20016,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-history.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20074,7 +20074,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. ", "responses": { "200": { "description": "Project", @@ -20094,7 +20094,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-personal-data-check.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20152,7 +20152,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -20172,7 +20172,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-session-alerts.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20230,7 +20230,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific authentication method. Use this endpoint to enable or disable different authentication methods such as email, magic urls or sms in your project. ", "responses": { "200": { "description": "Project", @@ -20250,7 +20250,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20329,7 +20329,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -20349,7 +20349,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-jwt.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20415,7 +20415,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -20435,7 +20435,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-keys.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20472,7 +20472,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project.", "responses": { "201": { "description": "Key", @@ -20492,7 +20492,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20564,7 +20564,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes.", "responses": { "200": { "description": "Key", @@ -20584,7 +20584,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20631,7 +20631,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. ", "responses": { "200": { "description": "Key", @@ -20651,7 +20651,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20731,7 +20731,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. ", "responses": { "204": { "description": "No content" @@ -20744,7 +20744,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20793,7 +20793,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable\/disable providers. ", "responses": { "200": { "description": "Project", @@ -20813,7 +20813,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-oauth2.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20929,7 +20929,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. ", "responses": { "200": { "description": "Platforms List", @@ -20949,7 +20949,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-platforms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20986,7 +20986,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new platform for your project. Use this endpoint to register a new platform where your users will run your application which will interact with the Appwrite API.", "responses": { "201": { "description": "Platform", @@ -21006,7 +21006,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21104,7 +21104,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. ", "responses": { "200": { "description": "Platform", @@ -21124,7 +21124,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21171,7 +21171,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. ", "responses": { "200": { "description": "Platform", @@ -21191,7 +21191,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21272,7 +21272,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. ", "responses": { "204": { "description": "No content" @@ -21285,7 +21285,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21334,7 +21334,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -21354,7 +21354,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21433,7 +21433,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -21453,7 +21453,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status-all.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21511,7 +21511,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails. ", "responses": { "200": { "description": "Project", @@ -21531,7 +21531,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-smtp.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21635,7 +21635,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -21648,7 +21648,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-smtp-test.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21758,7 +21758,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -21778,7 +21778,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-team.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21836,7 +21836,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. ", "responses": { "200": { "description": "EmailTemplate", @@ -21856,7 +21856,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22059,7 +22059,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates.", "responses": { "200": { "description": "EmailTemplate", @@ -22079,7 +22079,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22322,7 +22322,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. ", "responses": { "200": { "description": "EmailTemplate", @@ -22342,7 +22342,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22547,7 +22547,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -22567,7 +22567,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22767,7 +22767,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. ", "responses": { "200": { "description": "SmsTemplate", @@ -22787,7 +22787,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23006,7 +23006,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. ", "responses": { "200": { "description": "SmsTemplate", @@ -23026,7 +23026,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23228,7 +23228,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all webhooks belonging to the project. You can use the query params to filter your results. ", "responses": { "200": { "description": "Webhooks List", @@ -23248,7 +23248,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-webhooks.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23285,7 +23285,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. ", "responses": { "201": { "description": "Webhook", @@ -23305,7 +23305,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23399,7 +23399,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -23419,7 +23419,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23466,7 +23466,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. ", "responses": { "200": { "description": "Webhook", @@ -23486,7 +23486,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23588,7 +23588,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -23601,7 +23601,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23650,7 +23650,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the webhook signature key. This endpoint can be used to regenerate the signature key used to sign and validate payload deliveries for a specific webhook. ", "responses": { "200": { "description": "Webhook", @@ -23670,7 +23670,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook-signature.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23982,7 +23982,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Retry getting verification process of a proxy rule. This endpoint triggers domain verification by checking DNS records (CNAME) against the configured target domain. If verification is successful, a TLS certificate will be automatically provisioned for the domain.", "responses": { "200": { "description": "Rule", @@ -24002,7 +24002,7 @@ "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/update-rule-verification.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -25241,7 +25241,7 @@ "tags": [ "storage" ], - "description": "", + "description": "Get usage metrics and statistics for all buckets in the project. You can view the total number of buckets, files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "StorageUsage", @@ -25261,7 +25261,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -25312,7 +25312,7 @@ "tags": [ "storage" ], - "description": "", + "description": "Get usage metrics and statistics a specific bucket in the project. You can view the total number of files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "UsageBuckets", @@ -25332,7 +25332,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -27423,7 +27423,7 @@ "tags": [ "users" ], - "description": "", + "description": "Get usage metrics and statistics for all users in the project. You can view the total number of users and sessions. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "UsageUsers", @@ -27443,7 +27443,7 @@ "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -29696,7 +29696,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of GitHub repositories available through your installation. This endpoint returns repositories with their basic information, detected runtime environments, and latest push dates. You can optionally filter repositories using a search term. Each repository's runtime is automatically detected based on its contents and language statistics. The GitHub installation must be properly configured for this endpoint to work.", "responses": { "200": { "description": "Provider Repositories List", @@ -29716,7 +29716,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repositories.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -29764,7 +29764,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Create a new GitHub repository through your installation. This endpoint allows you to create either a public or private repository by specifying a name and visibility setting. The repository will be created under your GitHub user account or organization, depending on your installation type. The GitHub installation must be properly configured and have the necessary permissions for repository creation.", "responses": { "200": { "description": "ProviderRepository", @@ -29784,7 +29784,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -29848,7 +29848,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get detailed information about a specific GitHub repository from your installation. This endpoint returns repository details including its ID, name, visibility status, organization, and latest push date. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.", "responses": { "200": { "description": "ProviderRepository", @@ -29868,7 +29868,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -29917,7 +29917,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of all branches from a GitHub repository in your installation. This endpoint returns the names of all branches in the repository and their total count. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.\n", "responses": { "200": { "description": "Branches List", @@ -29937,7 +29937,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repository-branches.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -29986,7 +29986,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.\n", "responses": { "200": { "description": "VCS Content List", @@ -30006,7 +30006,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository-contents.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30066,7 +30066,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Analyze a GitHub repository to automatically detect the programming language and runtime environment. This endpoint scans the repository's files and language statistics to determine the appropriate runtime settings for your function. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.", "responses": { "200": { "description": "Detection", @@ -30086,7 +30086,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository-detection.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30151,7 +30151,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Authorize and create deployments for a GitHub pull request in your project. This endpoint allows external contributions by creating deployments from pull requests, enabling preview environments for code review. The pull request must be open and not previously authorized. The GitHub installation must be properly configured and have access to both the repository and pull request for this endpoint to work.", "responses": { "204": { "description": "No content" @@ -30164,7 +30164,7 @@ "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/update-external-deployments.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30232,7 +30232,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details.\n", "responses": { "200": { "description": "Installations List", @@ -30305,7 +30305,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. ", "responses": { "200": { "description": "Installation", @@ -30362,7 +30362,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project.", "responses": { "204": { "description": "No content" diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index d0630d8ac1..aee66626cf 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -9267,7 +9267,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "204": { "description": "No content" @@ -9280,7 +9280,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9345,7 +9345,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Build", @@ -9365,7 +9365,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 17eef07fdc..5369cd4c92 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -2508,7 +2508,7 @@ "tags": [ "account" ], - "description": "", + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", "responses": { "201": { "description": "Target", @@ -2524,7 +2524,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2591,7 +2591,7 @@ "tags": [ "account" ], - "description": "", + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", "responses": { "200": { "description": "Target", @@ -2607,7 +2607,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2665,7 +2665,7 @@ "tags": [ "account" ], - "description": "", + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", "responses": { "204": { "description": "No content" @@ -2678,7 +2678,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index b2f4797690..f9a423d954 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -2535,7 +2535,7 @@ "tags": [ "account" ], - "description": "", + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", "responses": { "201": { "description": "Target", @@ -2551,7 +2551,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2617,7 +2617,7 @@ "tags": [ "account" ], - "description": "", + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", "responses": { "200": { "description": "Target", @@ -2633,7 +2633,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -2690,7 +2690,7 @@ "tags": [ "account" ], - "description": "", + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", "responses": { "204": { "description": "No content" @@ -2703,7 +2703,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -4486,7 +4486,7 @@ "tags": [ "assistant" ], - "description": "", + "description": "Send a prompt to the AI assistant and receive a response. This endpoint allows you to interact with Appwrite's AI assistant by sending questions or prompts and receiving helpful responses in real-time through a server-sent events stream. ", "responses": { "200": { "description": "File", @@ -4758,7 +4758,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageDatabases", @@ -4774,7 +4774,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -8887,7 +8887,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageCollection", @@ -8903,7 +8903,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9045,7 +9045,7 @@ "tags": [ "databases" ], - "description": "", + "description": "Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", "responses": { "200": { "description": "UsageDatabase", @@ -9061,7 +9061,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-database-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9720,7 +9720,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for all functions. View statistics including total functions, deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunctions", @@ -9736,7 +9736,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-functions-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10514,7 +10514,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "204": { "description": "No content" @@ -10527,7 +10527,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10592,7 +10592,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Build", @@ -10608,7 +10608,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -11062,7 +11062,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", "responses": { "200": { "description": "UsageFunction", @@ -11078,7 +11078,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -17946,7 +17946,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "List all migrations in the current project. This endpoint returns a list of all migrations including their status, progress, and any errors that occurred during the migration process.", "responses": { "200": { "description": "Migrations List", @@ -18018,7 +18018,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from another Appwrite project to your current project. This endpoint allows you to migrate resources like databases, collections, documents, users, and files from an existing Appwrite project. ", "responses": { "202": { "description": "Migration", @@ -18111,7 +18111,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in an Appwrite project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", "responses": { "200": { "description": "Migration Report", @@ -18198,7 +18198,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from a Firebase project to your Appwrite project. This endpoint allows you to migrate resources like authentication and other supported services from a Firebase project. ", "responses": { "202": { "description": "Migration", @@ -18277,7 +18277,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in a Firebase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", "responses": { "200": { "description": "Migration Report", @@ -18347,7 +18347,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from an NHost project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from an NHost project. ", "responses": { "202": { "description": "Migration", @@ -18467,7 +18467,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a detailed report of the data in an NHost project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", "responses": { "200": { "description": "Migration Report", @@ -18586,7 +18586,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Migrate data from a Supabase project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from a Supabase project. ", "responses": { "202": { "description": "Migration", @@ -18699,7 +18699,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Generate a report of the data in a Supabase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", "responses": { "200": { "description": "Migration Report", @@ -18811,7 +18811,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Get a migration by its unique ID. This endpoint returns detailed information about a specific migration including its current status, progress, and any errors that occurred during the migration process. ", "responses": { "200": { "description": "Migration", @@ -18868,7 +18868,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -18923,7 +18923,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. ", "responses": { "204": { "description": "No content" @@ -18979,7 +18979,7 @@ "tags": [ "project" ], - "description": "", + "description": "Get comprehensive usage statistics for your project. View metrics including network requests, bandwidth, storage, function executions, database usage, and user activity. Specify a time range with startDate and endDate, and optionally set the data granularity with period (1h or 1d). The response includes both total counts and detailed breakdowns by resource, along with historical data over the specified period.", "responses": { "200": { "description": "UsageProject", @@ -18995,7 +18995,7 @@ "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19377,7 +19377,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -19393,7 +19393,7 @@ "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19447,7 +19447,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -19463,7 +19463,7 @@ "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19596,7 +19596,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a project by its unique ID. This endpoint allows you to retrieve the project's details, including its name, description, team, region, and other metadata. ", "responses": { "200": { "description": "Project", @@ -19612,7 +19612,7 @@ "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19653,7 +19653,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -19669,7 +19669,7 @@ "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19780,7 +19780,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -19793,7 +19793,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19836,7 +19836,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime.", "responses": { "200": { "description": "Project", @@ -19852,7 +19852,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -19927,7 +19927,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all API types. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime all at once.", "responses": { "200": { "description": "Project", @@ -19943,7 +19943,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status-all.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20004,7 +20004,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -20020,7 +20020,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-duration.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20081,7 +20081,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -20097,7 +20097,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-limit.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20158,7 +20158,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of sessions allowed per user within the project, if the limit is hit the oldest session will be deleted to make room for new sessions.", "responses": { "200": { "description": "Project", @@ -20174,7 +20174,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-sessions-limit.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20235,7 +20235,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update project membership privacy settings. Use this endpoint to control what user information is visible to other team members, such as user name, email, and MFA status. ", "responses": { "200": { "description": "Project", @@ -20251,7 +20251,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-memberships-privacy.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20326,7 +20326,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -20342,7 +20342,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-mock-numbers.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20406,7 +20406,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. ", "responses": { "200": { "description": "Project", @@ -20422,7 +20422,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-dictionary.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20483,7 +20483,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the authentication password history requirement. Use this endpoint to require new passwords to be different than the last X amount of previously used ones.", "responses": { "200": { "description": "Project", @@ -20499,7 +20499,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-history.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20560,7 +20560,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. ", "responses": { "200": { "description": "Project", @@ -20576,7 +20576,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-personal-data-check.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20637,7 +20637,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -20653,7 +20653,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-session-alerts.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20714,7 +20714,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific authentication method. Use this endpoint to enable or disable different authentication methods such as email, magic urls or sms in your project. ", "responses": { "200": { "description": "Project", @@ -20730,7 +20730,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20810,7 +20810,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -20826,7 +20826,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-jwt.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20896,7 +20896,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -20912,7 +20912,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-keys.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -20953,7 +20953,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project.", "responses": { "201": { "description": "Key", @@ -20969,7 +20969,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21046,7 +21046,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes.", "responses": { "200": { "description": "Key", @@ -21062,7 +21062,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21111,7 +21111,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. ", "responses": { "200": { "description": "Key", @@ -21127,7 +21127,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21208,7 +21208,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. ", "responses": { "204": { "description": "No content" @@ -21221,7 +21221,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-key.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21272,7 +21272,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable\/disable providers. ", "responses": { "200": { "description": "Project", @@ -21288,7 +21288,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-oauth2.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21410,7 +21410,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. ", "responses": { "200": { "description": "Platforms List", @@ -21426,7 +21426,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-platforms.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21467,7 +21467,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new platform for your project. Use this endpoint to register a new platform where your users will run your application which will interact with the Appwrite API.", "responses": { "201": { "description": "Platform", @@ -21483,7 +21483,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21588,7 +21588,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. ", "responses": { "200": { "description": "Platform", @@ -21604,7 +21604,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21653,7 +21653,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. ", "responses": { "200": { "description": "Platform", @@ -21669,7 +21669,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21752,7 +21752,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. ", "responses": { "204": { "description": "No content" @@ -21765,7 +21765,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-platform.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21816,7 +21816,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -21832,7 +21832,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21915,7 +21915,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -21931,7 +21931,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status-all.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -21992,7 +21992,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails. ", "responses": { "200": { "description": "Project", @@ -22008,7 +22008,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-smtp.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22123,7 +22123,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -22136,7 +22136,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-smtp-test.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22257,7 +22257,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -22273,7 +22273,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-team.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22334,7 +22334,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. ", "responses": { "200": { "description": "EmailTemplate", @@ -22350,7 +22350,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22553,7 +22553,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates.", "responses": { "200": { "description": "EmailTemplate", @@ -22569,7 +22569,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -22815,7 +22815,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. ", "responses": { "200": { "description": "EmailTemplate", @@ -22831,7 +22831,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-email-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23036,7 +23036,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -23052,7 +23052,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23252,7 +23252,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. ", "responses": { "200": { "description": "SmsTemplate", @@ -23268,7 +23268,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23486,7 +23486,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. ", "responses": { "200": { "description": "SmsTemplate", @@ -23502,7 +23502,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-sms-template.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23704,7 +23704,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all webhooks belonging to the project. You can use the query params to filter your results. ", "responses": { "200": { "description": "Webhooks List", @@ -23720,7 +23720,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-webhooks.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23761,7 +23761,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. ", "responses": { "201": { "description": "Webhook", @@ -23777,7 +23777,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23880,7 +23880,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -23896,7 +23896,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -23945,7 +23945,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. ", "responses": { "200": { "description": "Webhook", @@ -23961,7 +23961,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -24068,7 +24068,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -24081,7 +24081,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-webhook.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -24132,7 +24132,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the webhook signature key. This endpoint can be used to regenerate the signature key used to sign and validate payload deliveries for a specific webhook. ", "responses": { "200": { "description": "Webhook", @@ -24148,7 +24148,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook-signature.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -24468,7 +24468,7 @@ "tags": [ "proxy" ], - "description": "", + "description": "Retry getting verification process of a proxy rule. This endpoint triggers domain verification by checking DNS records (CNAME) against the configured target domain. If verification is successful, a TLS certificate will be automatically provisioned for the domain.", "responses": { "200": { "description": "Rule", @@ -24484,7 +24484,7 @@ "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/update-rule-verification.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -25727,7 +25727,7 @@ "tags": [ "storage" ], - "description": "", + "description": "Get usage metrics and statistics for all buckets in the project. You can view the total number of buckets, files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "StorageUsage", @@ -25743,7 +25743,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -25798,7 +25798,7 @@ "tags": [ "storage" ], - "description": "", + "description": "Get usage metrics and statistics a specific bucket in the project. You can view the total number of files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "UsageBuckets", @@ -25814,7 +25814,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -27964,7 +27964,7 @@ "tags": [ "users" ], - "description": "", + "description": "Get usage metrics and statistics for all users in the project. You can view the total number of users and sessions. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", "responses": { "200": { "description": "UsageUsers", @@ -27980,7 +27980,7 @@ "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30229,7 +30229,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of GitHub repositories available through your installation. This endpoint returns repositories with their basic information, detected runtime environments, and latest push dates. You can optionally filter repositories using a search term. Each repository's runtime is automatically detected based on its contents and language statistics. The GitHub installation must be properly configured for this endpoint to work.", "responses": { "200": { "description": "Provider Repositories List", @@ -30245,7 +30245,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repositories.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30295,7 +30295,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Create a new GitHub repository through your installation. This endpoint allows you to create either a public or private repository by specifying a name and visibility setting. The repository will be created under your GitHub user account or organization, depending on your installation type. The GitHub installation must be properly configured and have the necessary permissions for repository creation.", "responses": { "200": { "description": "ProviderRepository", @@ -30311,7 +30311,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30379,7 +30379,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get detailed information about a specific GitHub repository from your installation. This endpoint returns repository details including its ID, name, visibility status, organization, and latest push date. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.", "responses": { "200": { "description": "ProviderRepository", @@ -30395,7 +30395,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30446,7 +30446,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of all branches from a GitHub repository in your installation. This endpoint returns the names of all branches in the repository and their total count. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.\n", "responses": { "200": { "description": "Branches List", @@ -30462,7 +30462,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repository-branches.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30513,7 +30513,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.\n", "responses": { "200": { "description": "VCS Content List", @@ -30529,7 +30529,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository-contents.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30589,7 +30589,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Analyze a GitHub repository to automatically detect the programming language and runtime environment. This endpoint scans the repository's files and language statistics to determine the appropriate runtime settings for your function. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.", "responses": { "200": { "description": "Detection", @@ -30605,7 +30605,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository-detection.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30671,7 +30671,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Authorize and create deployments for a GitHub pull request in your project. This endpoint allows external contributions by creating deployments from pull requests, enabling preview environments for code review. The pull request must be open and not previously authorized. The GitHub installation must be properly configured and have access to both the repository and pull request for this endpoint to work.", "responses": { "204": { "description": "No content" @@ -30684,7 +30684,7 @@ "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/update-external-deployments.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -30753,7 +30753,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details.\n", "responses": { "200": { "description": "Installations List", @@ -30825,7 +30825,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. ", "responses": { "200": { "description": "Installation", @@ -30880,7 +30880,7 @@ "tags": [ "vcs" ], - "description": "", + "description": "Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project.", "responses": { "204": { "description": "No content" diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 3d787172a9..a3c6a0d70c 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -9450,7 +9450,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", "responses": { "204": { "description": "No content" @@ -9463,7 +9463,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9529,7 +9529,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", "responses": { "200": { "description": "Build", @@ -9545,7 +9545,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index c40d7601c4..48d20cd17f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -69,7 +69,7 @@ App::post('/v1/projects') ->label('sdk', new Method( namespace: 'projects', name: 'create', - description: '', + description: '/docs/references/projects/create.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -298,7 +298,7 @@ App::get('/v1/projects') ->label('sdk', new Method( namespace: 'projects', name: 'list', - description: '', + description: '/docs/references/projects/list.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -363,7 +363,7 @@ App::get('/v1/projects/:projectId') ->label('sdk', new Method( namespace: 'projects', name: 'get', - description: '', + description: '/docs/references/projects/get.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -395,7 +395,7 @@ App::patch('/v1/projects/:projectId') ->label('sdk', new Method( namespace: 'projects', name: 'update', - description: '', + description: '/docs/references/projects/update.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -448,7 +448,7 @@ App::patch('/v1/projects/:projectId/team') ->label('sdk', new Method( namespace: 'projects', name: 'updateTeam', - description: '', + description: '/docs/references/projects/update-team.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -522,7 +522,7 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk', new Method( namespace: 'projects', name: 'updateServiceStatus', - description: '', + description: '/docs/references/projects/update-service-status.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -559,7 +559,7 @@ App::patch('/v1/projects/:projectId/service/all') ->label('sdk', new Method( namespace: 'projects', name: 'updateServiceStatusAll', - description: '', + description: '/docs/references/projects/update-service-status-all.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -599,7 +599,7 @@ App::patch('/v1/projects/:projectId/api') ->label('sdk', new Method( namespace: 'projects', name: 'updateApiStatus', - description: '', + description: '/docs/references/projects/update-api-status.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -636,7 +636,7 @@ App::patch('/v1/projects/:projectId/api/all') ->label('sdk', new Method( namespace: 'projects', name: 'updateApiStatusAll', - description: '', + description: '/docs/references/projects/update-api-status-all.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -676,7 +676,7 @@ App::patch('/v1/projects/:projectId/oauth2') ->label('sdk', new Method( namespace: 'projects', name: 'updateOAuth2', - description: '', + description: '/docs/references/projects/update-oauth2.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -726,7 +726,7 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') ->label('sdk', new Method( namespace: 'projects', name: 'updateSessionAlerts', - description: '', + description: '/docs/references/projects/update-session-alerts.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -763,7 +763,7 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') ->label('sdk', new Method( namespace: 'projects', name: 'updateMembershipsPrivacy', - description: '', + description: '/docs/references/projects/update-memberships-privacy.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -804,7 +804,7 @@ App::patch('/v1/projects/:projectId/auth/limit') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthLimit', - description: '', + description: '/docs/references/projects/update-auth-limit.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -841,7 +841,7 @@ App::patch('/v1/projects/:projectId/auth/duration') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthDuration', - description: '', + description: '/docs/references/projects/update-auth-duration.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -878,7 +878,7 @@ App::patch('/v1/projects/:projectId/auth/:method') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthStatus', - description: '', + description: '/docs/references/projects/update-auth-status.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -918,7 +918,7 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthPasswordHistory', - description: '', + description: '/docs/references/projects/update-auth-password-history.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -955,7 +955,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthPasswordDictionary', - description: '', + description: '/docs/references/projects/update-auth-password-dictionary.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -992,7 +992,7 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->label('sdk', new Method( namespace: 'projects', name: 'updatePersonalDataCheck', - description: '', + description: '/docs/references/projects/update-personal-data-check.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1029,7 +1029,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->label('sdk', new Method( namespace: 'projects', name: 'updateAuthSessionsLimit', - description: '', + description: '/docs/references/projects/update-auth-sessions-limit.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1066,7 +1066,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') ->label('sdk', new Method( namespace: 'projects', name: 'updateMockNumbers', - description: '', + description: '/docs/references/projects/update-mock-numbers.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1113,7 +1113,7 @@ App::delete('/v1/projects/:projectId') ->label('sdk', new Method( namespace: 'projects', name: 'delete', - description: '', + description: '/docs/references/projects/delete.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1156,7 +1156,7 @@ App::post('/v1/projects/:projectId/webhooks') ->label('sdk', new Method( namespace: 'projects', name: 'createWebhook', - description: '', + description: '/docs/references/projects/create-webhook.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1220,7 +1220,7 @@ App::get('/v1/projects/:projectId/webhooks') ->label('sdk', new Method( namespace: 'projects', name: 'listWebhooks', - description: '', + description: '/docs/references/projects/list-webhooks.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1258,7 +1258,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->label('sdk', new Method( namespace: 'projects', name: 'getWebhook', - description: '', + description: '/docs/references/projects/get-webhook.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1298,7 +1298,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->label('sdk', new Method( namespace: 'projects', name: 'updateWebhook', - description: '', + description: '/docs/references/projects/update-webhook.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1363,7 +1363,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->label('sdk', new Method( namespace: 'projects', name: 'updateWebhookSignature', - description: '', + description: '/docs/references/projects/update-webhook-signature.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1408,7 +1408,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->label('sdk', new Method( namespace: 'projects', name: 'deleteWebhook', - description: '', + description: '/docs/references/projects/delete-webhook.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1455,7 +1455,7 @@ App::post('/v1/projects/:projectId/keys') ->label('sdk', new Method( namespace: 'projects', name: 'createKey', - description: '', + description: '/docs/references/projects/create-key.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1511,7 +1511,7 @@ App::get('/v1/projects/:projectId/keys') ->label('sdk', new Method( namespace: 'projects', name: 'listKeys', - description: '', + description: '/docs/references/projects/list-keys.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1549,7 +1549,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->label('sdk', new Method( namespace: 'projects', name: 'getKey', - description: '', + description: '/docs/references/projects/get-key.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1589,7 +1589,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->label('sdk', new Method( namespace: 'projects', name: 'updateKey', - description: '', + description: '/docs/references/projects/update-key.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1641,7 +1641,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->label('sdk', new Method( namespace: 'projects', name: 'deleteKey', - description: '', + description: '/docs/references/projects/delete-key.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1688,7 +1688,7 @@ App::post('/v1/projects/:projectId/jwts') ->label('sdk', new Method( namespace: 'projects', name: 'createJWT', - description: '', + description: '/docs/references/projects/create-jwt.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1731,7 +1731,7 @@ App::post('/v1/projects/:projectId/platforms') ->label('sdk', new Method( namespace: 'projects', name: 'createPlatform', - description: '', + description: '/docs/references/projects/create-platform.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1787,7 +1787,7 @@ App::get('/v1/projects/:projectId/platforms') ->label('sdk', new Method( namespace: 'projects', name: 'listPlatforms', - description: '', + description: '/docs/references/projects/list-platforms.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1825,7 +1825,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->label('sdk', new Method( namespace: 'projects', name: 'getPlatform', - description: '', + description: '/docs/references/projects/get-platform.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1865,7 +1865,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->label('sdk', new Method( namespace: 'projects', name: 'updatePlatform', - description: '', + description: '/docs/references/projects/update-platform.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1920,7 +1920,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->label('sdk', new Method( namespace: 'projects', name: 'deletePlatform', - description: '', + description: '/docs/references/projects/delete-platform.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -1967,7 +1967,7 @@ App::patch('/v1/projects/:projectId/smtp') ->label('sdk', new Method( namespace: 'projects', name: 'updateSmtp', - description: '', + description: '/docs/references/projects/update-smtp.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2063,7 +2063,7 @@ App::post('/v1/projects/:projectId/smtp/tests') ->label('sdk', new Method( namespace: 'projects', name: 'createSmtpTest', - description: '', + description: '/docs/references/projects/create-smtp-test.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2129,7 +2129,7 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'getSmsTemplate', - description: '', + description: '/docs/references/projects/get-sms-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2176,7 +2176,7 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'getEmailTemplate', - description: '', + description: '/docs/references/projects/get-email-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2234,7 +2234,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'updateSmsTemplate', - description: '', + description: '/docs/references/projects/update-sms-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2280,7 +2280,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'updateEmailTemplate', - description: '', + description: '/docs/references/projects/update-email-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2336,7 +2336,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'deleteSmsTemplate', - description: '', + description: '/docs/references/projects/delete-sms-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( @@ -2386,7 +2386,7 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk', new Method( namespace: 'projects', name: 'deleteEmailTemplate', - description: '', + description: '/docs/references/projects/delete-email-template.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( diff --git a/docs/references/assistant/chat.md b/docs/references/assistant/chat.md new file mode 100644 index 0000000000..5297d1c195 --- /dev/null +++ b/docs/references/assistant/chat.md @@ -0,0 +1 @@ +Send a prompt to the AI assistant and receive a response. This endpoint allows you to interact with Appwrite's AI assistant by sending questions or prompts and receiving helpful responses in real-time through a server-sent events stream. \ No newline at end of file diff --git a/docs/references/migrations/delete-migration.md b/docs/references/migrations/delete-migration.md new file mode 100644 index 0000000000..9d361ac693 --- /dev/null +++ b/docs/references/migrations/delete-migration.md @@ -0,0 +1 @@ +Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. \ No newline at end of file diff --git a/docs/references/migrations/get-migration.md b/docs/references/migrations/get-migration.md new file mode 100644 index 0000000000..710bef6863 --- /dev/null +++ b/docs/references/migrations/get-migration.md @@ -0,0 +1 @@ +Get a migration by its unique ID. This endpoint returns detailed information about a specific migration including its current status, progress, and any errors that occurred during the migration process. \ No newline at end of file diff --git a/docs/references/migrations/list-migrations.md b/docs/references/migrations/list-migrations.md new file mode 100644 index 0000000000..b1acb3f7b3 --- /dev/null +++ b/docs/references/migrations/list-migrations.md @@ -0,0 +1 @@ +List all migrations in the current project. This endpoint returns a list of all migrations including their status, progress, and any errors that occurred during the migration process. \ No newline at end of file diff --git a/docs/references/migrations/migration-appwrite-report.md b/docs/references/migrations/migration-appwrite-report.md new file mode 100644 index 0000000000..69d556f5f3 --- /dev/null +++ b/docs/references/migrations/migration-appwrite-report.md @@ -0,0 +1 @@ +Generate a report of the data in an Appwrite project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. \ No newline at end of file diff --git a/docs/references/migrations/migration-appwrite.md b/docs/references/migrations/migration-appwrite.md new file mode 100644 index 0000000000..12ee742387 --- /dev/null +++ b/docs/references/migrations/migration-appwrite.md @@ -0,0 +1 @@ +Migrate data from another Appwrite project to your current project. This endpoint allows you to migrate resources like databases, collections, documents, users, and files from an existing Appwrite project. \ No newline at end of file diff --git a/docs/references/migrations/migration-firebase-report.md b/docs/references/migrations/migration-firebase-report.md new file mode 100644 index 0000000000..af27587331 --- /dev/null +++ b/docs/references/migrations/migration-firebase-report.md @@ -0,0 +1 @@ +Generate a report of the data in a Firebase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. \ No newline at end of file diff --git a/docs/references/migrations/migration-firebase.md b/docs/references/migrations/migration-firebase.md new file mode 100644 index 0000000000..3a7f620a7c --- /dev/null +++ b/docs/references/migrations/migration-firebase.md @@ -0,0 +1 @@ +Migrate data from a Firebase project to your Appwrite project. This endpoint allows you to migrate resources like authentication and other supported services from a Firebase project. \ No newline at end of file diff --git a/docs/references/migrations/migration-nhost-report.md b/docs/references/migrations/migration-nhost-report.md new file mode 100644 index 0000000000..895da51464 --- /dev/null +++ b/docs/references/migrations/migration-nhost-report.md @@ -0,0 +1 @@ +Generate a detailed report of the data in an NHost project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. \ No newline at end of file diff --git a/docs/references/migrations/migration-nhost.md b/docs/references/migrations/migration-nhost.md new file mode 100644 index 0000000000..b7a727dd2b --- /dev/null +++ b/docs/references/migrations/migration-nhost.md @@ -0,0 +1 @@ +Migrate data from an NHost project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from an NHost project. \ No newline at end of file diff --git a/docs/references/migrations/migration-supabase-report.md b/docs/references/migrations/migration-supabase-report.md new file mode 100644 index 0000000000..d9636b5f1d --- /dev/null +++ b/docs/references/migrations/migration-supabase-report.md @@ -0,0 +1 @@ +Generate a report of the data in a Supabase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. \ No newline at end of file diff --git a/docs/references/migrations/migration-supabase.md b/docs/references/migrations/migration-supabase.md new file mode 100644 index 0000000000..34bbb1eece --- /dev/null +++ b/docs/references/migrations/migration-supabase.md @@ -0,0 +1 @@ +Migrate data from a Supabase project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from a Supabase project. \ No newline at end of file diff --git a/docs/references/migrations/retry-migration.md b/docs/references/migrations/retry-migration.md new file mode 100644 index 0000000000..49b80ad6d4 --- /dev/null +++ b/docs/references/migrations/retry-migration.md @@ -0,0 +1 @@ +Retry a failed migration. This endpoint allows you to retry a migration that has previously failed. \ No newline at end of file diff --git a/docs/references/projects/create-jwt.md b/docs/references/projects/create-jwt.md new file mode 100644 index 0000000000..9a6f8ebf6b --- /dev/null +++ b/docs/references/projects/create-jwt.md @@ -0,0 +1 @@ +Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. \ No newline at end of file diff --git a/docs/references/projects/create-key.md b/docs/references/projects/create-key.md new file mode 100644 index 0000000000..d6633d936d --- /dev/null +++ b/docs/references/projects/create-key.md @@ -0,0 +1 @@ +Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project. \ No newline at end of file diff --git a/docs/references/projects/create-platform.md b/docs/references/projects/create-platform.md new file mode 100644 index 0000000000..b5d8be0ff9 --- /dev/null +++ b/docs/references/projects/create-platform.md @@ -0,0 +1 @@ +Create a new platform for your project. Use this endpoint to register a new platform where your users will run your application which will interact with the Appwrite API. \ No newline at end of file diff --git a/docs/references/projects/create-smtp-test.md b/docs/references/projects/create-smtp-test.md new file mode 100644 index 0000000000..63cea9d21f --- /dev/null +++ b/docs/references/projects/create-smtp-test.md @@ -0,0 +1 @@ +Send a test email to verify SMTP configuration. \ No newline at end of file diff --git a/docs/references/projects/create-webhook.md b/docs/references/projects/create-webhook.md new file mode 100644 index 0000000000..cd0e93332b --- /dev/null +++ b/docs/references/projects/create-webhook.md @@ -0,0 +1 @@ +Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. \ No newline at end of file diff --git a/docs/references/projects/create.md b/docs/references/projects/create.md new file mode 100644 index 0000000000..d502c269ef --- /dev/null +++ b/docs/references/projects/create.md @@ -0,0 +1 @@ +Create a new project. You can create a maximum of 100 projects per account. \ No newline at end of file diff --git a/docs/references/projects/delete-email-template.md b/docs/references/projects/delete-email-template.md new file mode 100644 index 0000000000..332b1d6117 --- /dev/null +++ b/docs/references/projects/delete-email-template.md @@ -0,0 +1 @@ +Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. \ No newline at end of file diff --git a/docs/references/projects/delete-key.md b/docs/references/projects/delete-key.md new file mode 100644 index 0000000000..9f3774b419 --- /dev/null +++ b/docs/references/projects/delete-key.md @@ -0,0 +1 @@ +Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. \ No newline at end of file diff --git a/docs/references/projects/delete-platform.md b/docs/references/projects/delete-platform.md new file mode 100644 index 0000000000..7d538cac26 --- /dev/null +++ b/docs/references/projects/delete-platform.md @@ -0,0 +1 @@ +Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. \ No newline at end of file diff --git a/docs/references/projects/delete-sms-template.md b/docs/references/projects/delete-sms-template.md new file mode 100644 index 0000000000..c5a7e6cac9 --- /dev/null +++ b/docs/references/projects/delete-sms-template.md @@ -0,0 +1 @@ +Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. \ No newline at end of file diff --git a/docs/references/projects/delete-webhook.md b/docs/references/projects/delete-webhook.md new file mode 100644 index 0000000000..74fee2bcec --- /dev/null +++ b/docs/references/projects/delete-webhook.md @@ -0,0 +1 @@ +Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. \ No newline at end of file diff --git a/docs/references/projects/delete.md b/docs/references/projects/delete.md new file mode 100644 index 0000000000..4a8070c082 --- /dev/null +++ b/docs/references/projects/delete.md @@ -0,0 +1 @@ +Delete a project by its unique ID. \ No newline at end of file diff --git a/docs/references/projects/get-email-template.md b/docs/references/projects/get-email-template.md new file mode 100644 index 0000000000..6119a0a183 --- /dev/null +++ b/docs/references/projects/get-email-template.md @@ -0,0 +1 @@ +Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. \ No newline at end of file diff --git a/docs/references/projects/get-key.md b/docs/references/projects/get-key.md new file mode 100644 index 0000000000..bd6351f420 --- /dev/null +++ b/docs/references/projects/get-key.md @@ -0,0 +1 @@ +Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes. \ No newline at end of file diff --git a/docs/references/projects/get-platform.md b/docs/references/projects/get-platform.md new file mode 100644 index 0000000000..87129b829d --- /dev/null +++ b/docs/references/projects/get-platform.md @@ -0,0 +1 @@ +Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. \ No newline at end of file diff --git a/docs/references/projects/get-sms-template.md b/docs/references/projects/get-sms-template.md new file mode 100644 index 0000000000..6ef1d93029 --- /dev/null +++ b/docs/references/projects/get-sms-template.md @@ -0,0 +1 @@ +Get a custom SMS template for the specified locale and type returning it's contents. \ No newline at end of file diff --git a/docs/references/projects/get-webhook.md b/docs/references/projects/get-webhook.md new file mode 100644 index 0000000000..559c73c748 --- /dev/null +++ b/docs/references/projects/get-webhook.md @@ -0,0 +1 @@ +Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. \ No newline at end of file diff --git a/docs/references/projects/get.md b/docs/references/projects/get.md new file mode 100644 index 0000000000..b7a1165adc --- /dev/null +++ b/docs/references/projects/get.md @@ -0,0 +1 @@ +Get a project by its unique ID. This endpoint allows you to retrieve the project's details, including its name, description, team, region, and other metadata. \ No newline at end of file diff --git a/docs/references/projects/list-keys.md b/docs/references/projects/list-keys.md new file mode 100644 index 0000000000..a7b701b0d7 --- /dev/null +++ b/docs/references/projects/list-keys.md @@ -0,0 +1 @@ +Get a list of all API keys from the current project. \ No newline at end of file diff --git a/docs/references/projects/list-platforms.md b/docs/references/projects/list-platforms.md new file mode 100644 index 0000000000..ed9ade0852 --- /dev/null +++ b/docs/references/projects/list-platforms.md @@ -0,0 +1 @@ +Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. \ No newline at end of file diff --git a/docs/references/projects/list-webhooks.md b/docs/references/projects/list-webhooks.md new file mode 100644 index 0000000000..bbbf4c7376 --- /dev/null +++ b/docs/references/projects/list-webhooks.md @@ -0,0 +1 @@ +Get a list of all webhooks belonging to the project. You can use the query params to filter your results. \ No newline at end of file diff --git a/docs/references/projects/list.md b/docs/references/projects/list.md new file mode 100644 index 0000000000..576a4b79ae --- /dev/null +++ b/docs/references/projects/list.md @@ -0,0 +1 @@ +Get a list of all projects. You can use the query params to filter your results. \ No newline at end of file diff --git a/docs/references/projects/update-api-status-all.md b/docs/references/projects/update-api-status-all.md new file mode 100644 index 0000000000..654070759f --- /dev/null +++ b/docs/references/projects/update-api-status-all.md @@ -0,0 +1 @@ +Update the status of all API types. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime all at once. \ No newline at end of file diff --git a/docs/references/projects/update-api-status.md b/docs/references/projects/update-api-status.md new file mode 100644 index 0000000000..af10a0d4f4 --- /dev/null +++ b/docs/references/projects/update-api-status.md @@ -0,0 +1 @@ +Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime. \ No newline at end of file diff --git a/docs/references/projects/update-auth-duration.md b/docs/references/projects/update-auth-duration.md new file mode 100644 index 0000000000..bdc75fa6f0 --- /dev/null +++ b/docs/references/projects/update-auth-duration.md @@ -0,0 +1 @@ +Update how long sessions created within a project should stay active for. \ No newline at end of file diff --git a/docs/references/projects/update-auth-limit.md b/docs/references/projects/update-auth-limit.md new file mode 100644 index 0000000000..c8faa3fe37 --- /dev/null +++ b/docs/references/projects/update-auth-limit.md @@ -0,0 +1 @@ +Update the maximum number of users allowed in this project. Set to 0 for unlimited users. \ No newline at end of file diff --git a/docs/references/projects/update-auth-password-dictionary.md b/docs/references/projects/update-auth-password-dictionary.md new file mode 100644 index 0000000000..1d47d30bb5 --- /dev/null +++ b/docs/references/projects/update-auth-password-dictionary.md @@ -0,0 +1 @@ +Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. \ No newline at end of file diff --git a/docs/references/projects/update-auth-password-history.md b/docs/references/projects/update-auth-password-history.md new file mode 100644 index 0000000000..3a892915d5 --- /dev/null +++ b/docs/references/projects/update-auth-password-history.md @@ -0,0 +1 @@ +Update the authentication password history requirement. Use this endpoint to require new passwords to be different than the last X amount of previously used ones. \ No newline at end of file diff --git a/docs/references/projects/update-auth-sessions-limit.md b/docs/references/projects/update-auth-sessions-limit.md new file mode 100644 index 0000000000..7d5fdffae7 --- /dev/null +++ b/docs/references/projects/update-auth-sessions-limit.md @@ -0,0 +1 @@ +Update the maximum number of sessions allowed per user within the project, if the limit is hit the oldest session will be deleted to make room for new sessions. \ No newline at end of file diff --git a/docs/references/projects/update-auth-status.md b/docs/references/projects/update-auth-status.md new file mode 100644 index 0000000000..5d39ec29c4 --- /dev/null +++ b/docs/references/projects/update-auth-status.md @@ -0,0 +1 @@ +Update the status of a specific authentication method. Use this endpoint to enable or disable different authentication methods such as email, magic urls or sms in your project. \ No newline at end of file diff --git a/docs/references/projects/update-email-template.md b/docs/references/projects/update-email-template.md new file mode 100644 index 0000000000..d2bf124541 --- /dev/null +++ b/docs/references/projects/update-email-template.md @@ -0,0 +1 @@ +Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates. \ No newline at end of file diff --git a/docs/references/projects/update-key.md b/docs/references/projects/update-key.md new file mode 100644 index 0000000000..4934a51497 --- /dev/null +++ b/docs/references/projects/update-key.md @@ -0,0 +1 @@ +Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. \ No newline at end of file diff --git a/docs/references/projects/update-memberships-privacy.md b/docs/references/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..a1affc1166 --- /dev/null +++ b/docs/references/projects/update-memberships-privacy.md @@ -0,0 +1 @@ +Update project membership privacy settings. Use this endpoint to control what user information is visible to other team members, such as user name, email, and MFA status. \ No newline at end of file diff --git a/docs/references/projects/update-mock-numbers.md b/docs/references/projects/update-mock-numbers.md new file mode 100644 index 0000000000..7fa92455c1 --- /dev/null +++ b/docs/references/projects/update-mock-numbers.md @@ -0,0 +1 @@ +Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. \ No newline at end of file diff --git a/docs/references/projects/update-oauth2.md b/docs/references/projects/update-oauth2.md new file mode 100644 index 0000000000..2285135991 --- /dev/null +++ b/docs/references/projects/update-oauth2.md @@ -0,0 +1 @@ +Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable/disable providers. \ No newline at end of file diff --git a/docs/references/projects/update-personal-data-check.md b/docs/references/projects/update-personal-data-check.md new file mode 100644 index 0000000000..42847fdbfc --- /dev/null +++ b/docs/references/projects/update-personal-data-check.md @@ -0,0 +1 @@ +Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. \ No newline at end of file diff --git a/docs/references/projects/update-platform.md b/docs/references/projects/update-platform.md new file mode 100644 index 0000000000..d04b07bafd --- /dev/null +++ b/docs/references/projects/update-platform.md @@ -0,0 +1 @@ +Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. \ No newline at end of file diff --git a/docs/references/projects/update-service-status-all.md b/docs/references/projects/update-service-status-all.md new file mode 100644 index 0000000000..f05e7d8c5c --- /dev/null +++ b/docs/references/projects/update-service-status-all.md @@ -0,0 +1 @@ +Update the status of all services. Use this endpoint to enable or disable all optional services at once. \ No newline at end of file diff --git a/docs/references/projects/update-service-status.md b/docs/references/projects/update-service-status.md new file mode 100644 index 0000000000..9d3b0743a8 --- /dev/null +++ b/docs/references/projects/update-service-status.md @@ -0,0 +1 @@ +Update the status of a specific service. Use this endpoint to enable or disable a service in your project. \ No newline at end of file diff --git a/docs/references/projects/update-session-alerts.md b/docs/references/projects/update-session-alerts.md new file mode 100644 index 0000000000..36859e0c1e --- /dev/null +++ b/docs/references/projects/update-session-alerts.md @@ -0,0 +1 @@ +Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created. \ No newline at end of file diff --git a/docs/references/projects/update-sms-template.md b/docs/references/projects/update-sms-template.md new file mode 100644 index 0000000000..3e67f613b7 --- /dev/null +++ b/docs/references/projects/update-sms-template.md @@ -0,0 +1 @@ +Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. \ No newline at end of file diff --git a/docs/references/projects/update-smtp.md b/docs/references/projects/update-smtp.md new file mode 100644 index 0000000000..7d898e1ed1 --- /dev/null +++ b/docs/references/projects/update-smtp.md @@ -0,0 +1 @@ +Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails. \ No newline at end of file diff --git a/docs/references/projects/update-team.md b/docs/references/projects/update-team.md new file mode 100644 index 0000000000..fb02eda88c --- /dev/null +++ b/docs/references/projects/update-team.md @@ -0,0 +1 @@ +Update the team ID of a project allowing for it to be transferred to another team. \ No newline at end of file diff --git a/docs/references/projects/update-webhook-signature.md b/docs/references/projects/update-webhook-signature.md new file mode 100644 index 0000000000..8525a05777 --- /dev/null +++ b/docs/references/projects/update-webhook-signature.md @@ -0,0 +1 @@ +Update the webhook signature key. This endpoint can be used to regenerate the signature key used to sign and validate payload deliveries for a specific webhook. \ No newline at end of file diff --git a/docs/references/projects/update-webhook.md b/docs/references/projects/update-webhook.md new file mode 100644 index 0000000000..745e4aebe1 --- /dev/null +++ b/docs/references/projects/update-webhook.md @@ -0,0 +1 @@ +Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. \ No newline at end of file diff --git a/docs/references/projects/update.md b/docs/references/projects/update.md new file mode 100644 index 0000000000..60c072c477 --- /dev/null +++ b/docs/references/projects/update.md @@ -0,0 +1 @@ +Update a project by its unique ID. \ No newline at end of file diff --git a/docs/references/vcs/delete-installation.md b/docs/references/vcs/delete-installation.md new file mode 100644 index 0000000000..1f07de364d --- /dev/null +++ b/docs/references/vcs/delete-installation.md @@ -0,0 +1 @@ +Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project. \ No newline at end of file diff --git a/docs/references/vcs/get-installation.md b/docs/references/vcs/get-installation.md new file mode 100644 index 0000000000..0679d9a0e9 --- /dev/null +++ b/docs/references/vcs/get-installation.md @@ -0,0 +1 @@ +Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. \ No newline at end of file diff --git a/docs/references/vcs/list-installations.md b/docs/references/vcs/list-installations.md new file mode 100644 index 0000000000..e77daf7db0 --- /dev/null +++ b/docs/references/vcs/list-installations.md @@ -0,0 +1 @@ +List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details. diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php index 8064b75561..4495af3e09 100644 --- a/src/Appwrite/SDK/Method.php +++ b/src/Appwrite/SDK/Method.php @@ -48,7 +48,7 @@ class Method ) { $this->validateMethod($name, $namespace); $this->validateAuthTypes($auth); - //$this->validateDesc($description); + $this->validateDesc($description); foreach ($responses as $response) { /** @var SDKResponse $response */ From 731529455554f7e27cc78e46dc8fa84a89494345 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 20 Jan 2025 05:44:19 +0000 Subject: [PATCH 327/340] fix: phone number parsing exception handling --- app/controllers/api/account.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 6935029450..592b72e83a 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -28,6 +28,7 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use libphonenumber\NumberParseException; use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; @@ -2467,7 +2468,12 @@ App::post('/v1/account/tokens/phone') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - $countryCode = $helper->parse($phone)->getCountryCode(); + + try { + $countryCode = $helper->parse($phone)->getCountryCode(); + } catch (NumberParseException $e) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); + } if (!empty($countryCode)) { $queueForUsage @@ -3587,7 +3593,12 @@ App::post('/v1/account/verification/phone') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - $countryCode = $helper->parse($phone)->getCountryCode(); + + try { + $countryCode = $helper->parse($phone)->getCountryCode(); + } catch (NumberParseException $e) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); + } if (!empty($countryCode)) { $queueForUsage @@ -4148,7 +4159,12 @@ App::post('/v1/account/mfa/challenge') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - $countryCode = $helper->parse($phone)->getCountryCode(); + + try { + $countryCode = $helper->parse($phone)->getCountryCode(); + } catch (NumberParseException $e) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); + } if (!empty($countryCode)) { $queueForUsage From 8fb772340f2f6a5623e9689646808b1d159bded7 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 20 Jan 2025 08:12:42 +0000 Subject: [PATCH 328/340] chore: shifted validation --- app/controllers/api/account.php | 22 +++------------------- src/Appwrite/Auth/Validator/Phone.php | 13 +++++++++++++ tests/unit/Auth/Validator/PhoneTest.php | 1 + 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 592b72e83a..6935029450 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -28,7 +28,6 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; -use libphonenumber\NumberParseException; use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; @@ -2468,12 +2467,7 @@ App::post('/v1/account/tokens/phone') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - - try { - $countryCode = $helper->parse($phone)->getCountryCode(); - } catch (NumberParseException $e) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); - } + $countryCode = $helper->parse($phone)->getCountryCode(); if (!empty($countryCode)) { $queueForUsage @@ -3593,12 +3587,7 @@ App::post('/v1/account/verification/phone') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - - try { - $countryCode = $helper->parse($phone)->getCountryCode(); - } catch (NumberParseException $e) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); - } + $countryCode = $helper->parse($phone)->getCountryCode(); if (!empty($countryCode)) { $queueForUsage @@ -4159,12 +4148,7 @@ App::post('/v1/account/mfa/challenge') $abuse = new Abuse($timelimit); if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { $helper = PhoneNumberUtil::getInstance(); - - try { - $countryCode = $helper->parse($phone)->getCountryCode(); - } catch (NumberParseException $e) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid phone number'); - } + $countryCode = $helper->parse($phone)->getCountryCode(); if (!empty($countryCode)) { $queueForUsage diff --git a/src/Appwrite/Auth/Validator/Phone.php b/src/Appwrite/Auth/Validator/Phone.php index 26aa687278..2ad4d4fad7 100644 --- a/src/Appwrite/Auth/Validator/Phone.php +++ b/src/Appwrite/Auth/Validator/Phone.php @@ -2,6 +2,8 @@ namespace Appwrite\Auth\Validator; +use libphonenumber\NumberParseException; +use libphonenumber\PhoneNumberUtil; use Utopia\Validator; /** @@ -12,10 +14,12 @@ use Utopia\Validator; class Phone extends Validator { protected bool $allowEmpty; + protected PhoneNumberUtil $helper; public function __construct(bool $allowEmpty = false) { $this->allowEmpty = $allowEmpty; + $this->helper = PhoneNumberUtil::getInstance(); } /** @@ -47,6 +51,15 @@ class Phone extends Validator return true; } + try { + $parsedValue = $this->helper->parse($value); + if (!$this->helper->isValidNumber($parsedValue)) { + return false; + } + } catch (NumberParseException $e) { + return false; + } + return !!\preg_match('/^\+[1-9]\d{6,14}$/', $value); } diff --git a/tests/unit/Auth/Validator/PhoneTest.php b/tests/unit/Auth/Validator/PhoneTest.php index d5a4e7f826..e9103e608a 100644 --- a/tests/unit/Auth/Validator/PhoneTest.php +++ b/tests/unit/Auth/Validator/PhoneTest.php @@ -31,6 +31,7 @@ class PhoneTest extends TestCase $this->assertEquals($this->object->isValid('+0415553452342'), false); $this->assertEquals($this->object->isValid('+14 155 5524564'), false); $this->assertEquals($this->object->isValid('+1415555245634543'), false); + $this->assertEquals($this->object->isValid('+8027547935'), false); $this->assertEquals($this->object->isValid(+14155552456), false); $this->assertEquals($this->object->isValid('+1415555'), true); From ca0459046d21b04c9445c5a4e4c6c0f46d7c18b1 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 20 Jan 2025 08:33:49 +0000 Subject: [PATCH 329/340] chore: remove isValidNumber check --- src/Appwrite/Auth/Validator/Phone.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Appwrite/Auth/Validator/Phone.php b/src/Appwrite/Auth/Validator/Phone.php index 2ad4d4fad7..e74a78d265 100644 --- a/src/Appwrite/Auth/Validator/Phone.php +++ b/src/Appwrite/Auth/Validator/Phone.php @@ -52,10 +52,7 @@ class Phone extends Validator } try { - $parsedValue = $this->helper->parse($value); - if (!$this->helper->isValidNumber($parsedValue)) { - return false; - } + $this->helper->parse($value); } catch (NumberParseException $e) { return false; } From b87c750536aa98bb2ab462636dfb4e27a0d827a9 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Mon, 20 Jan 2025 14:31:22 +0530 Subject: [PATCH 330/340] chore: add temporary check to deletes worker to prevent it from throwing an exception --- src/Appwrite/Platform/Workers/Deletes.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 539bbd61f9..a72bd2be77 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -201,10 +201,15 @@ class Deletes extends Action 'message' => 'messages' }; - $resource = $getProjectDB($project)->getDocument( - $collectionId, - $document->getAttribute('resourceId') - ); + try { + $resource = $getProjectDB($project)->getDocument( + $collectionId, + $document->getAttribute('resourceId') + ); + } catch (Throwable $e) { + Console::error('Failed to get resource for schedule ' . $document->getId() . ' ' . $e->getMessage()); + return; + } $delete = true; From 9c95c162d97a448d52d90779899edf7c7ec7e70b Mon Sep 17 00:00:00 2001 From: fogelito <fogelshmuel@gmail.com> Date: Mon, 20 Jan 2025 11:28:48 +0200 Subject: [PATCH 331/340] bumb database version --- composer.json | 2 +- composer.lock | 58 +++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 84fcd355d7..d90f09fb2b 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.56.3", + "utopia-php/database": "0.56.4", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index dea3ad41f6..d85fb52461 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": "92b40e75d531c98b72508dd104eeab0d", + "content-hash": "7ef4409cc1690563b87dffc0d52b06d5", "packages": [ { "name": "adhocore/jwt", @@ -3136,16 +3136,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.46.2", + "version": "0.47.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "59749df988430b28953fb5cabfad88b0ff5b539b" + "reference": "2b52bb362234d4072b647ed57db1b3be030f57c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/59749df988430b28953fb5cabfad88b0ff5b539b", - "reference": "59749df988430b28953fb5cabfad88b0ff5b539b", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/2b52bb362234d4072b647ed57db1b3be030f57c2", + "reference": "2b52bb362234d4072b647ed57db1b3be030f57c2", "shasum": "" }, "require": { @@ -3153,7 +3153,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.32" + "utopia-php/database": "0.56.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3181,9 +3181,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.46.2" + "source": "https://github.com/utopia-php/abuse/tree/0.47.0" }, - "time": "2025-01-13T02:09:43+00:00" + "time": "2025-01-15T02:41:02+00:00" }, { "name": "utopia-php/analytics", @@ -3233,21 +3233,21 @@ }, { "name": "utopia-php/audit", - "version": "0.46.1", + "version": "0.47.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37" + "reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/21255fa1ce66433140a43d380b2859c7f0a0bb37", - "reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/1ebd5784ba68645073426f2f04a67726a1bde4d7", + "reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.53.32" + "utopia-php/database": "0.56.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -3274,9 +3274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.46.1" + "source": "https://github.com/utopia-php/audit/tree/0.47.0" }, - "time": "2025-01-13T02:19:56+00:00" + "time": "2025-01-15T02:40:53+00:00" }, { "name": "utopia-php/cache", @@ -3476,16 +3476,16 @@ }, { "name": "utopia-php/database", - "version": "0.53.32", + "version": "0.56.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "981a1241139b42dccd531511130b79137740b205" + "reference": "240478a60797124a885ceac40046fe47c22415b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205", - "reference": "981a1241139b42dccd531511130b79137740b205", + "url": "https://api.github.com/repos/utopia-php/database/zipball/240478a60797124a885ceac40046fe47c22415b7", + "reference": "240478a60797124a885ceac40046fe47c22415b7", "shasum": "" }, "require": { @@ -3526,9 +3526,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.32" + "source": "https://github.com/utopia-php/database/tree/0.56.4" }, - "time": "2025-01-10T08:53:47+00:00" + "time": "2025-01-20T09:22:08+00:00" }, { "name": "utopia-php/domains", @@ -3929,16 +3929,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.14", + "version": "0.6.15", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2" + "reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", - "reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/e849ec3e7ad38f5f5273ebb0132b112639cdf01c", + "reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c", "shasum": "" }, "require": { @@ -3946,7 +3946,7 @@ "ext-curl": "*", "ext-openssl": "*", "php": "8.3.*", - "utopia-php/database": "0.53.*", + "utopia-php/database": "0.56.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" @@ -3979,9 +3979,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.14" + "source": "https://github.com/utopia-php/migration/tree/0.6.15" }, - "time": "2025-01-08T01:07:25+00:00" + "time": "2025-01-15T04:55:08+00:00" }, { "name": "utopia-php/mongo", @@ -8556,7 +8556,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 2533a95b8b0ceca817300c0b3da57f1ceb3f87d0 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Mon, 20 Jan 2025 15:13:50 +0530 Subject: [PATCH 332/340] chore: add missing case for executions --- src/Appwrite/Platform/Workers/Deletes.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index a72bd2be77..46ae480684 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -198,6 +198,7 @@ class Deletes extends Action $collectionId = match ($document->getAttribute('resourceType')) { 'function' => 'functions', + 'execution' => 'executions', 'message' => 'messages' }; @@ -217,6 +218,9 @@ class Deletes extends Action case 'function': $delete = $resource->isEmpty(); break; + case 'execution': + $delete = false; + break; } if ($delete) { From 07630c272defa75a938d37fd16cafb05a9f46225 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Mon, 20 Jan 2025 12:41:57 +0000 Subject: [PATCH 333/340] chore: update test --- tests/unit/Auth/Validator/PhoneTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Auth/Validator/PhoneTest.php b/tests/unit/Auth/Validator/PhoneTest.php index e9103e608a..b5308ac8a9 100644 --- a/tests/unit/Auth/Validator/PhoneTest.php +++ b/tests/unit/Auth/Validator/PhoneTest.php @@ -31,7 +31,7 @@ class PhoneTest extends TestCase $this->assertEquals($this->object->isValid('+0415553452342'), false); $this->assertEquals($this->object->isValid('+14 155 5524564'), false); $this->assertEquals($this->object->isValid('+1415555245634543'), false); - $this->assertEquals($this->object->isValid('+8027547935'), false); + $this->assertEquals($this->object->isValid('+8020000000'), false); $this->assertEquals($this->object->isValid(+14155552456), false); $this->assertEquals($this->object->isValid('+1415555'), true); From af8cb29bfbeaf877a8f0866c17648e1eb916204a Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Tue, 21 Jan 2025 05:41:47 +0000 Subject: [PATCH 334/340] chore: added log --- src/Appwrite/Platform/Workers/Certificates.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 0ae40b2df0..e763cb54ee 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -147,7 +147,8 @@ class Certificates extends Action // If certificate exists already, double-check expiry date. Skip if job is forced if (!$certificates->isRenewRequired($domain->get(), $log)) { - throw new Exception('Renew isn\'t required.'); + Console::info("Skipping, renew isn't required"); + return; } } From f8f403a66aa421b6053244899c1c08ad252b8b95 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 21 Jan 2025 12:02:08 +0530 Subject: [PATCH 335/340] remove: comments. --- app/controllers/shared/api.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index b231903d8e..012ff3d420 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -259,7 +259,6 @@ App::init() Authorization::setRole(Auth::USER_ROLE_APPS); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - // dynamic api key user $queueForAudits->setUser($user); } } elseif ($keyType === API_KEY_STANDARD) { @@ -311,7 +310,6 @@ App::init() } } - // standard api key user $queueForAudits->setUser($user); } } From 3c3559aee5be3d814cc7e5b7bb7e0b40be2db1b1 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 21 Jan 2025 12:07:03 +0530 Subject: [PATCH 336/340] update: apply comment suggestion. --- app/controllers/shared/api.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 012ff3d420..086129f116 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -520,8 +520,7 @@ App::init() ->setEvent($route->getLabel('audits.event', '')) ->setProject($project); - // check first, - // as api key user might already exists + /* If a session exists, use the user associated with the session */ if (!$user->isEmpty()) { $typedUser = clone $user; // $user doesn't support `type` and can cause unintended effects. From bc533aeeaacf0ad279a754305622e1efbe0e6392 Mon Sep 17 00:00:00 2001 From: Darshan <itznotabug@gmail.com> Date: Tue, 21 Jan 2025 12:11:20 +0530 Subject: [PATCH 337/340] update: change var name. --- app/controllers/shared/api.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 086129f116..dafebb735d 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -522,10 +522,10 @@ App::init() /* If a session exists, use the user associated with the session */ if (!$user->isEmpty()) { - $typedUser = clone $user; + $userClone = clone $user; // $user doesn't support `type` and can cause unintended effects. - $typedUser->setAttribute('type', Auth::ACTIVITY_TYPE_USER); - $queueForAudits->setUser($typedUser); + $userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($userClone); } $queueForDeletes->setProject($project); @@ -734,10 +734,10 @@ App::shutdown() } if (!$user->isEmpty()) { - $typedUser = clone $user; + $userClone = clone $user; // $user doesn't support `type` and can cause unintended effects. - $typedUser->setAttribute('type', Auth::ACTIVITY_TYPE_USER); - $queueForAudits->setUser($typedUser); + $userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($userClone); } elseif ($queueForAudits->getUser() === null || $queueForAudits->getUser()->isEmpty()) { /** * User in the request is empty, and no user was set for auditing previously. From 27459cc2c0497ecadcd284076dd6de14eedceb3d Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Tue, 21 Jan 2025 07:04:16 +0000 Subject: [PATCH 338/340] chore: added test comment --- tests/unit/Auth/Validator/PhoneTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Auth/Validator/PhoneTest.php b/tests/unit/Auth/Validator/PhoneTest.php index b5308ac8a9..b7730641c3 100644 --- a/tests/unit/Auth/Validator/PhoneTest.php +++ b/tests/unit/Auth/Validator/PhoneTest.php @@ -31,7 +31,7 @@ class PhoneTest extends TestCase $this->assertEquals($this->object->isValid('+0415553452342'), false); $this->assertEquals($this->object->isValid('+14 155 5524564'), false); $this->assertEquals($this->object->isValid('+1415555245634543'), false); - $this->assertEquals($this->object->isValid('+8020000000'), false); + $this->assertEquals($this->object->isValid('+8020000000'), false); // when country code is not present $this->assertEquals($this->object->isValid(+14155552456), false); $this->assertEquals($this->object->isValid('+1415555'), true); From 5123cf5f8eabcedf363ea675ed76c3395aec99d7 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Wed, 22 Jan 2025 11:08:23 +0900 Subject: [PATCH 339/340] Make Method Extendable --- src/Appwrite/SDK/Method.php | 24 +++++++++++++------ .../Specification/Format/OpenAPI3.php | 2 +- .../Specification/Format/Swagger2.php | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php index 4495af3e09..bbeb80595f 100644 --- a/src/Appwrite/SDK/Method.php +++ b/src/Appwrite/SDK/Method.php @@ -57,12 +57,12 @@ class Method } } - private function getRouteName(): string + protected function getRouteName(): string { return $this->namespace . '.' . $this->name; } - private function validateMethod(string $name, string $namespace): void + protected function validateMethod(string $name, string $namespace): void { if (\in_array($this->getRouteName(), self::$processed)) { self::$errors[] = "Error with {$this->getRouteName()} method: Method already exists in namespace {$namespace}"; @@ -71,7 +71,7 @@ class Method self::$processed[] = $this->getRouteName(); } - private function validateAuthTypes(array $authTypes): void + protected function validateAuthTypes(array $authTypes): void { foreach ($authTypes as $authType) { if (!($authType instanceof AuthType)) { @@ -80,14 +80,14 @@ class Method } } - private function validateDesc(string $desc): void + protected function validateDesc(string $desc): void { if (empty($desc)) { self::$errors[] = "Error with {$this->getRouteName()} method: Description label is empty"; return; } - $descPath = \realpath(__DIR__ . '/../../../' . $desc); + $descPath = $this->getDescriptionFilePath(); if (!\file_exists($descPath)) { self::$errors[] = "Error with {$this->getRouteName()} method: Description file not found at {$desc}"; @@ -95,7 +95,7 @@ class Method } } - private function validateResponseModel(string|array $responseModel): void + protected function validateResponseModel(string|array $responseModel): void { $response = new Response(new HttpResponse()); @@ -112,7 +112,7 @@ class Method } } - private function validateNoContent(SDKResponse $response): void + protected function validateNoContent(SDKResponse $response): void { if ($response->getCode() === 204) { if ($response->getModel() !== Response::MODEL_NONE) { @@ -136,6 +136,16 @@ class Method return $this->description; } + /** + * This method returns the absolute path to the description file returning null if the file does not exist. + * + * @return string|null + */ + public function getDescriptionFilePath(): ?string + { + return \realpath(__DIR__ . '/../../../' . $this->getDescription()) ?: null; + } + public function getAuth(): array { return $this->auth; diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 02568a8ccf..bd5405539d 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -148,7 +148,7 @@ class OpenAPI3 extends Format $method = array_keys($method)[0]; } - $desc = (!empty($sdk->getDescription())) ? \realpath(__DIR__ . '/../../../../' . $sdk->getDescription()) : null; + $desc = $sdk->getDescriptionFilePath(); $produces = ($sdk->getContentType())->value; $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 22aac47113..7277e3ab2b 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -144,7 +144,7 @@ class Swagger2 extends Format $method = array_keys($method)[0]; } - $desc = (!empty($sdk->getDescription())) ? \realpath(__DIR__ . '/../../../../' . $sdk->getDescription()) : null; + $desc = $sdk->getDescriptionFilePath(); $produces = ($sdk->getContentType())->value; $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; From df491f6f4607d79c1c350913d6174ad0bd191515 Mon Sep 17 00:00:00 2001 From: Bradley Schofield <ionicisere@gmail.com> Date: Wed, 22 Jan 2025 16:02:56 +0900 Subject: [PATCH 340/340] Fix null deprecation warning --- src/Appwrite/SDK/Method.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php index bbeb80595f..626459ea7f 100644 --- a/src/Appwrite/SDK/Method.php +++ b/src/Appwrite/SDK/Method.php @@ -89,7 +89,7 @@ class Method $descPath = $this->getDescriptionFilePath(); - if (!\file_exists($descPath)) { + if (empty($descPath)) { self::$errors[] = "Error with {$this->getRouteName()} method: Description file not found at {$desc}"; return; }