Merge remote-tracking branch 'origin/fix-missing-filter' into fix-missing-filter

This commit is contained in:
Darshan 2025-04-29 18:40:06 +05:30
commit d9a065713b
17242 changed files with 186780 additions and 27956 deletions

1
.env
View file

@ -15,6 +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_CUSTOM_DOMAIN_DENY_LIST=
_APP_OPTIONS_ABUSE=disabled
_APP_OPTIONS_ROUTER_PROTECTION=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled

View file

@ -89,7 +89,6 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-migrations && \
chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-stats-usage && \
chmod +x /usr/local/bin/worker-stats-usage-dump && \
chmod +x /usr/local/bin/stats-resources && \
chmod +x /usr/local/bin/worker-stats-resources

View file

@ -219,6 +219,13 @@ CLI::setResource('queueForCertificates', function (Publisher $publisher) {
}, ['publisher']);
CLI::setResource('logError', function (Registry $register) {
return function (Throwable $error, string $namespace, string $action) use ($register) {
Console::error('[Error] Timestamp: ' . date('c', time()));
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $error->getMessage());
Console::error('[Error] File: ' . $error->getFile());
Console::error('[Error] Line: ' . $error->getLine());
Console::error('[Error] Trace: ' . $error->getTraceAsString());
$logger = $register->get('logger');
if ($logger) {
@ -237,6 +244,7 @@ CLI::setResource('logError', function (Registry $register) {
$log->addExtra('file', $error->getFile());
$log->addExtra('line', $error->getLine());
$log->addExtra('trace', $error->getTraceAsString());
$log->addExtra('detailedTrace', $error->getTrace());
$log->setAction($action);
@ -250,24 +258,34 @@ CLI::setResource('logError', function (Registry $register) {
Console::error('Error pushing log: ' . $th->getMessage());
}
}
Console::warning("Failed: {$error->getMessage()}");
Console::warning($error->getTraceAsString());
};
}, ['register']);
CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
$platform = new Appwrite();
$platform->init(Service::TYPE_TASK);
$args = $platform->getEnv('argv');
if (!isset($args[0])) {
Console::error('Missing task name');
Console::exit(1);
}
\array_shift($args);
$taskName = $args[0];
$platform->init(Service::TYPE_TASK);
$cli = $platform->getCli();
$cli
->error()
->inject('error')
->action(function (Throwable $error) {
Console::error($error->getMessage());
->inject('logError')
->action(function (Throwable $error, callable $logError) use ($taskName) {
call_user_func_array($logError, [
$error,
'Task',
$taskName,
]);
});
$cli->run();

View file

@ -1148,7 +1148,7 @@ return [
'format' => '',
'size' => 32,
'signed' => true,
'required' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],

View file

@ -651,6 +651,11 @@ return [
'description' => 'Database timed out. Try adjusting your queries or adding an index.',
'code' => 408
],
Exception::DATABASE_QUERY_ORDER_NULL => [
'name' => Exception::DATABASE_QUERY_ORDER_NULL,
'description' => 'The order attribute had a null value. Cursor pagination requires all documents order attribute values are non-null.',
'code' => 400,
],
/** Collections */
Exception::COLLECTION_NOT_FOUND => [

View file

@ -142,6 +142,16 @@ return [
'beta' => false,
'mock' => false,
],
'figma' => [
'name' => 'Figma',
'developers' => 'https://www.figma.com/developers/api#oauth2',
'icon' => 'icon-figma',
'enabled' => true,
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false,
],
'github' => [
'name' => 'GitHub',
'developers' => 'https://developer.github.com/',

View file

@ -11,7 +11,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '17.0.1',
'version' => '17.0.2',
'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' => '15.0.0',
'version' => '15.0.1',
'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' => '9.0.0',
'version' => '9.0.1',
'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.1.0',
'version' => '7.0.1',
'url' => 'https://github.com/appwrite/sdk-for-android',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
'enabled' => true,
@ -134,7 +134,7 @@ return [
[
'key' => 'react-native',
'name' => 'React Native',
'version' => '0.7.1',
'version' => '0.7.3',
'url' => 'https://github.com/appwrite/sdk-for-react-native',
'package' => 'https://npmjs.com/package/react-native-appwrite',
'enabled' => true,
@ -217,7 +217,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '6.2.2',
'version' => '6.2.3',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@ -245,7 +245,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '15.0.1',
'version' => '16.0.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.2.0',
'version' => '14.0.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.2.0',
'version' => '14.0.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' => '9.0.2',
'version' => '10.0.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.2.0',
'version' => '15.0.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.3.0',
'version' => '0.5.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.11.0',
'version' => '0.12.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' => '14.0.0',
'version' => '15.0.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.2.0',
'version' => '8.0.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' => '8.0.0',
'version' => '9.0.0',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.6.1",
"version": "1.6.2",
"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",
@ -18,6 +18,9 @@
"servers": [
{
"url": "https:\/\/cloud.appwrite.io\/v1"
},
{
"url": "https:\/\/<REGION>.cloud.appwrite.io\/v1"
}
],
"paths": {
@ -43,6 +46,7 @@
},
"x-appwrite": {
"method": "get",
"group": "account",
"weight": 9,
"cookies": false,
"type": "",
@ -91,6 +95,7 @@
},
"x-appwrite": {
"method": "create",
"group": "account",
"weight": 8,
"cookies": false,
"type": "",
@ -175,6 +180,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"group": "account",
"weight": 34,
"cookies": false,
"type": "",
@ -250,6 +256,7 @@
},
"x-appwrite": {
"method": "listIdentities",
"group": "identities",
"weight": 57,
"cookies": false,
"type": "",
@ -308,6 +315,7 @@
},
"x-appwrite": {
"method": "deleteIdentity",
"group": "identities",
"weight": 58,
"cookies": false,
"type": "",
@ -370,6 +378,7 @@
},
"x-appwrite": {
"method": "createJWT",
"group": "tokens",
"weight": 29,
"cookies": false,
"type": "",
@ -418,6 +427,7 @@
},
"x-appwrite": {
"method": "listLogs",
"group": "logs",
"weight": 31,
"cookies": false,
"type": "",
@ -483,6 +493,7 @@
},
"x-appwrite": {
"method": "updateMFA",
"group": "mfa",
"weight": 44,
"cookies": false,
"type": "",
@ -552,6 +563,7 @@
},
"x-appwrite": {
"method": "createMfaAuthenticator",
"group": "mfa",
"weight": 46,
"cookies": false,
"type": "",
@ -597,7 +609,7 @@
]
},
"put": {
"summary": "Verify authenticator",
"summary": "Update authenticator (confirmation)",
"operationId": "accountUpdateMfaAuthenticator",
"tags": [
"account"
@ -617,6 +629,7 @@
},
"x-appwrite": {
"method": "updateMfaAuthenticator",
"group": "mfa",
"weight": 47,
"cookies": false,
"type": "",
@ -694,6 +707,7 @@
},
"x-appwrite": {
"method": "deleteMfaAuthenticator",
"group": "mfa",
"weight": 51,
"cookies": false,
"type": "",
@ -761,6 +775,7 @@
},
"x-appwrite": {
"method": "createMfaChallenge",
"group": "mfa",
"weight": 52,
"cookies": false,
"type": "",
@ -814,7 +829,7 @@
}
},
"put": {
"summary": "Create MFA challenge (confirmation)",
"summary": "Update MFA challenge (confirmation)",
"operationId": "accountUpdateMfaChallenge",
"tags": [
"account"
@ -834,6 +849,7 @@
},
"x-appwrite": {
"method": "updateMfaChallenge",
"group": "mfa",
"weight": 53,
"cookies": false,
"type": "",
@ -909,6 +925,7 @@
},
"x-appwrite": {
"method": "listMfaFactors",
"group": "mfa",
"weight": 45,
"cookies": false,
"type": "",
@ -939,7 +956,7 @@
},
"\/account\/mfa\/recovery-codes": {
"get": {
"summary": "Get MFA recovery codes",
"summary": "List MFA recovery codes",
"operationId": "accountGetMfaRecoveryCodes",
"tags": [
"account"
@ -959,6 +976,7 @@
},
"x-appwrite": {
"method": "getMfaRecoveryCodes",
"group": "mfa",
"weight": 50,
"cookies": false,
"type": "",
@ -1007,6 +1025,7 @@
},
"x-appwrite": {
"method": "createMfaRecoveryCodes",
"group": "mfa",
"weight": 48,
"cookies": false,
"type": "",
@ -1035,7 +1054,7 @@
]
},
"patch": {
"summary": "Regenerate MFA recovery codes",
"summary": "Update MFA recovery codes (regenerate)",
"operationId": "accountUpdateMfaRecoveryCodes",
"tags": [
"account"
@ -1055,6 +1074,7 @@
},
"x-appwrite": {
"method": "updateMfaRecoveryCodes",
"group": "mfa",
"weight": 49,
"cookies": false,
"type": "",
@ -1105,6 +1125,7 @@
},
"x-appwrite": {
"method": "updateName",
"group": "account",
"weight": 32,
"cookies": false,
"type": "",
@ -1174,6 +1195,7 @@
},
"x-appwrite": {
"method": "updatePassword",
"group": "account",
"weight": 33,
"cookies": false,
"type": "",
@ -1248,6 +1270,7 @@
},
"x-appwrite": {
"method": "updatePhone",
"group": "account",
"weight": 35,
"cookies": false,
"type": "",
@ -1323,6 +1346,7 @@
},
"x-appwrite": {
"method": "getPrefs",
"group": "account",
"weight": 30,
"cookies": false,
"type": "",
@ -1371,6 +1395,7 @@
},
"x-appwrite": {
"method": "updatePrefs",
"group": "account",
"weight": 36,
"cookies": false,
"type": "",
@ -1440,6 +1465,7 @@
},
"x-appwrite": {
"method": "createRecovery",
"group": "recovery",
"weight": 38,
"cookies": false,
"type": "",
@ -1496,7 +1522,7 @@
}
},
"put": {
"summary": "Create password recovery (confirmation)",
"summary": "Update password recovery (confirmation)",
"operationId": "accountUpdateRecovery",
"tags": [
"account"
@ -1516,6 +1542,7 @@
},
"x-appwrite": {
"method": "updateRecovery",
"group": "recovery",
"weight": 39,
"cookies": false,
"type": "",
@ -1597,6 +1624,7 @@
},
"x-appwrite": {
"method": "listSessions",
"group": "sessions",
"weight": 11,
"cookies": false,
"type": "",
@ -1638,6 +1666,7 @@
},
"x-appwrite": {
"method": "deleteSessions",
"group": "sessions",
"weight": 12,
"cookies": false,
"type": "",
@ -1688,6 +1717,7 @@
},
"x-appwrite": {
"method": "createAnonymousSession",
"group": "sessions",
"weight": 17,
"cookies": false,
"type": "",
@ -1736,6 +1766,7 @@
},
"x-appwrite": {
"method": "createEmailPasswordSession",
"group": "sessions",
"weight": 16,
"cookies": false,
"type": "",
@ -1809,6 +1840,7 @@
},
"x-appwrite": {
"method": "updateMagicURLSession",
"group": "sessions",
"weight": 26,
"cookies": false,
"type": "",
@ -1875,6 +1907,7 @@
},
"x-appwrite": {
"method": "createOAuth2Session",
"group": "sessions",
"weight": 19,
"cookies": false,
"type": "webAuth",
@ -1902,7 +1935,7 @@
"parameters": [
{
"name": "provider",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"required": true,
"schema": {
"type": "string",
@ -1922,6 +1955,7 @@
"dropbox",
"etsy",
"facebook",
"figma",
"github",
"gitlab",
"google",
@ -2015,6 +2049,7 @@
},
"x-appwrite": {
"method": "updatePhoneSession",
"group": "sessions",
"weight": 27,
"cookies": false,
"type": "",
@ -2088,6 +2123,7 @@
},
"x-appwrite": {
"method": "createSession",
"group": "sessions",
"weight": 18,
"cookies": false,
"type": "",
@ -2161,6 +2197,7 @@
},
"x-appwrite": {
"method": "getSession",
"group": "sessions",
"weight": 13,
"cookies": false,
"type": "",
@ -2221,6 +2258,7 @@
},
"x-appwrite": {
"method": "updateSession",
"group": "sessions",
"weight": 15,
"cookies": false,
"type": "",
@ -2274,6 +2312,7 @@
},
"x-appwrite": {
"method": "deleteSession",
"group": "sessions",
"weight": 14,
"cookies": false,
"type": "",
@ -2336,6 +2375,7 @@
},
"x-appwrite": {
"method": "updateStatus",
"group": "account",
"weight": 37,
"cookies": false,
"type": "",
@ -2386,6 +2426,7 @@
},
"x-appwrite": {
"method": "createPushTarget",
"group": "pushTargets",
"weight": 54,
"cookies": false,
"type": "",
@ -2464,6 +2505,7 @@
},
"x-appwrite": {
"method": "updatePushTarget",
"group": "pushTargets",
"weight": 55,
"cookies": false,
"type": "",
@ -2534,6 +2576,7 @@
},
"x-appwrite": {
"method": "deletePushTarget",
"group": "pushTargets",
"weight": 56,
"cookies": false,
"type": "",
@ -2594,6 +2637,7 @@
},
"x-appwrite": {
"method": "createEmailToken",
"group": "tokens",
"weight": 25,
"cookies": false,
"type": "",
@ -2672,6 +2716,7 @@
},
"x-appwrite": {
"method": "createMagicURLToken",
"group": "tokens",
"weight": 24,
"cookies": false,
"type": "",
@ -2751,6 +2796,7 @@
},
"x-appwrite": {
"method": "createOAuth2Token",
"group": "tokens",
"weight": 23,
"cookies": false,
"type": "webAuth",
@ -2778,7 +2824,7 @@
"parameters": [
{
"name": "provider",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"required": true,
"schema": {
"type": "string",
@ -2798,6 +2844,7 @@
"dropbox",
"etsy",
"facebook",
"figma",
"github",
"gitlab",
"google",
@ -2891,6 +2938,7 @@
},
"x-appwrite": {
"method": "createPhoneToken",
"group": "tokens",
"weight": 28,
"cookies": false,
"type": "",
@ -2967,6 +3015,7 @@
},
"x-appwrite": {
"method": "createVerification",
"group": "verification",
"weight": 40,
"cookies": false,
"type": "",
@ -3014,7 +3063,7 @@
}
},
"put": {
"summary": "Create email verification (confirmation)",
"summary": "Update email verification (confirmation)",
"operationId": "accountUpdateVerification",
"tags": [
"account"
@ -3034,6 +3083,7 @@
},
"x-appwrite": {
"method": "updateVerification",
"group": "verification",
"weight": 41,
"cookies": false,
"type": "",
@ -3109,6 +3159,7 @@
},
"x-appwrite": {
"method": "createPhoneVerification",
"group": "verification",
"weight": 42,
"cookies": false,
"type": "",
@ -3160,6 +3211,7 @@
},
"x-appwrite": {
"method": "updatePhoneVerification",
"group": "verification",
"weight": 43,
"cookies": false,
"type": "",
@ -3228,6 +3280,7 @@
},
"x-appwrite": {
"method": "getBrowser",
"group": null,
"weight": 60,
"cookies": false,
"type": "location",
@ -3353,6 +3406,7 @@
},
"x-appwrite": {
"method": "getCreditCard",
"group": null,
"weight": 59,
"cookies": false,
"type": "location",
@ -3484,6 +3538,7 @@
},
"x-appwrite": {
"method": "getFavicon",
"group": null,
"weight": 63,
"cookies": false,
"type": "location",
@ -3541,6 +3596,7 @@
},
"x-appwrite": {
"method": "getFlag",
"group": null,
"weight": 61,
"cookies": false,
"type": "location",
@ -4028,6 +4084,7 @@
},
"x-appwrite": {
"method": "getImage",
"group": null,
"weight": 62,
"cookies": false,
"type": "location",
@ -4109,6 +4166,7 @@
},
"x-appwrite": {
"method": "getInitials",
"group": null,
"weight": 65,
"cookies": false,
"type": "location",
@ -4200,6 +4258,7 @@
},
"x-appwrite": {
"method": "getQR",
"group": null,
"weight": 64,
"cookies": false,
"type": "location",
@ -4298,6 +4357,7 @@
},
"x-appwrite": {
"method": "listDocuments",
"group": "documents",
"weight": 109,
"cookies": false,
"type": "",
@ -4382,6 +4442,7 @@
},
"x-appwrite": {
"method": "createDocument",
"group": "documents",
"weight": 108,
"cookies": false,
"type": "",
@ -4488,6 +4549,7 @@
},
"x-appwrite": {
"method": "getDocument",
"group": "documents",
"weight": 110,
"cookies": false,
"type": "",
@ -4582,6 +4644,7 @@
},
"x-appwrite": {
"method": "updateDocument",
"group": "documents",
"weight": 112,
"cookies": false,
"type": "",
@ -4680,6 +4743,7 @@
},
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 113,
"cookies": false,
"type": "",
@ -4763,7 +4827,8 @@
},
"x-appwrite": {
"method": "listExecutions",
"weight": 306,
"group": "executions",
"weight": 305,
"cookies": false,
"type": "",
"deprecated": false,
@ -4848,7 +4913,8 @@
},
"x-appwrite": {
"method": "createExecution",
"weight": 305,
"group": "executions",
"weight": 304,
"cookies": false,
"type": "",
"deprecated": false,
@ -4962,7 +5028,8 @@
},
"x-appwrite": {
"method": "getExecution",
"weight": 307,
"group": "executions",
"weight": 306,
"cookies": false,
"type": "",
"deprecated": false,
@ -5035,7 +5102,8 @@
},
"x-appwrite": {
"method": "query",
"weight": 331,
"group": "graphql",
"weight": 330,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5086,7 +5154,8 @@
},
"x-appwrite": {
"method": "mutation",
"weight": 330,
"group": "graphql",
"weight": 329,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5137,6 +5206,7 @@
},
"x-appwrite": {
"method": "get",
"group": null,
"weight": 117,
"cookies": false,
"type": "",
@ -5188,6 +5258,7 @@
},
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 118,
"cookies": false,
"type": "",
@ -5239,6 +5310,7 @@
},
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 122,
"cookies": false,
"type": "",
@ -5290,6 +5362,7 @@
},
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 119,
"cookies": false,
"type": "",
@ -5341,6 +5414,7 @@
},
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 120,
"cookies": false,
"type": "",
@ -5392,6 +5466,7 @@
},
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 121,
"cookies": false,
"type": "",
@ -5443,6 +5518,7 @@
},
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 123,
"cookies": false,
"type": "",
@ -5494,6 +5570,7 @@
},
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 124,
"cookies": false,
"type": "",
@ -5545,7 +5622,8 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 376,
"group": "subscribers",
"weight": 375,
"cookies": false,
"type": "",
"deprecated": false,
@ -5627,7 +5705,8 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 380,
"group": "subscribers",
"weight": 379,
"cookies": false,
"type": "",
"deprecated": false,
@ -5701,7 +5780,8 @@
},
"x-appwrite": {
"method": "listFiles",
"weight": 208,
"group": "files",
"weight": 207,
"cookies": false,
"type": "",
"deprecated": false,
@ -5786,7 +5866,8 @@
},
"x-appwrite": {
"method": "createFile",
"weight": 207,
"group": "files",
"weight": 206,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -5883,7 +5964,8 @@
},
"x-appwrite": {
"method": "getFile",
"weight": 209,
"group": "files",
"weight": 208,
"cookies": false,
"type": "",
"deprecated": false,
@ -5954,7 +6036,8 @@
},
"x-appwrite": {
"method": "updateFile",
"weight": 214,
"group": "files",
"weight": 213,
"cookies": false,
"type": "",
"deprecated": false,
@ -6042,7 +6125,8 @@
},
"x-appwrite": {
"method": "deleteFile",
"weight": 215,
"group": "files",
"weight": 214,
"cookies": false,
"type": "",
"deprecated": false,
@ -6108,7 +6192,8 @@
},
"x-appwrite": {
"method": "getFileDownload",
"weight": 211,
"group": "files",
"weight": 210,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6174,7 +6259,8 @@
},
"x-appwrite": {
"method": "getFilePreview",
"weight": 210,
"group": "files",
"weight": 209,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6390,7 +6476,8 @@
},
"x-appwrite": {
"method": "getFileView",
"weight": 212,
"group": "files",
"weight": 211,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6463,7 +6550,8 @@
},
"x-appwrite": {
"method": "list",
"weight": 219,
"group": "teams",
"weight": 218,
"cookies": false,
"type": "",
"deprecated": false,
@ -6538,7 +6626,8 @@
},
"x-appwrite": {
"method": "create",
"weight": 218,
"group": "teams",
"weight": 217,
"cookies": false,
"type": "",
"deprecated": false,
@ -6622,7 +6711,8 @@
},
"x-appwrite": {
"method": "get",
"weight": 220,
"group": "teams",
"weight": 219,
"cookies": false,
"type": "",
"deprecated": false,
@ -6683,7 +6773,8 @@
},
"x-appwrite": {
"method": "updateName",
"weight": 222,
"group": "teams",
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -6756,7 +6847,8 @@
},
"x-appwrite": {
"method": "delete",
"weight": 224,
"group": "teams",
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -6819,7 +6911,8 @@
},
"x-appwrite": {
"method": "listMemberships",
"weight": 226,
"group": "memberships",
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -6904,7 +6997,8 @@
},
"x-appwrite": {
"method": "createMembership",
"weight": 225,
"group": "memberships",
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -7014,7 +7108,8 @@
},
"x-appwrite": {
"method": "getMembership",
"weight": 227,
"group": "memberships",
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -7085,7 +7180,8 @@
},
"x-appwrite": {
"method": "updateMembership",
"weight": 228,
"group": "memberships",
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7171,7 +7267,8 @@
},
"x-appwrite": {
"method": "deleteMembership",
"weight": 230,
"group": "memberships",
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7244,7 +7341,8 @@
},
"x-appwrite": {
"method": "updateMembershipStatus",
"weight": 229,
"group": "memberships",
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -7341,7 +7439,8 @@
},
"x-appwrite": {
"method": "getPrefs",
"weight": 221,
"group": "teams",
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -7401,7 +7500,8 @@
},
"x-appwrite": {
"method": "updatePrefs",
"weight": 223,
"group": "teams",
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,9 @@
"servers": [
{
"url": "https:\/\/cloud.appwrite.io\/v1"
},
{
"url": "https:\/\/<REGION>.cloud.appwrite.io\/v1"
}
],
"paths": {
@ -43,6 +46,7 @@
},
"x-appwrite": {
"method": "get",
"group": "account",
"weight": 10,
"cookies": false,
"type": "",
@ -91,6 +95,7 @@
},
"x-appwrite": {
"method": "create",
"group": "account",
"weight": 9,
"cookies": false,
"type": "",
@ -175,6 +180,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"group": "account",
"weight": 35,
"cookies": false,
"type": "",
@ -250,6 +256,7 @@
},
"x-appwrite": {
"method": "listIdentities",
"group": "identities",
"weight": 58,
"cookies": false,
"type": "",
@ -308,6 +315,7 @@
},
"x-appwrite": {
"method": "deleteIdentity",
"group": "identities",
"weight": 59,
"cookies": false,
"type": "",
@ -370,6 +378,7 @@
},
"x-appwrite": {
"method": "createJWT",
"group": "tokens",
"weight": 30,
"cookies": false,
"type": "",
@ -418,6 +427,7 @@
},
"x-appwrite": {
"method": "listLogs",
"group": "logs",
"weight": 32,
"cookies": false,
"type": "",
@ -483,6 +493,7 @@
},
"x-appwrite": {
"method": "updateMFA",
"group": "mfa",
"weight": 45,
"cookies": false,
"type": "",
@ -552,6 +563,7 @@
},
"x-appwrite": {
"method": "createMfaAuthenticator",
"group": "mfa",
"weight": 47,
"cookies": false,
"type": "",
@ -597,7 +609,7 @@
]
},
"put": {
"summary": "Verify authenticator",
"summary": "Update authenticator (confirmation)",
"operationId": "accountUpdateMfaAuthenticator",
"tags": [
"account"
@ -617,6 +629,7 @@
},
"x-appwrite": {
"method": "updateMfaAuthenticator",
"group": "mfa",
"weight": 48,
"cookies": false,
"type": "",
@ -694,6 +707,7 @@
},
"x-appwrite": {
"method": "deleteMfaAuthenticator",
"group": "mfa",
"weight": 52,
"cookies": false,
"type": "",
@ -761,6 +775,7 @@
},
"x-appwrite": {
"method": "createMfaChallenge",
"group": "mfa",
"weight": 53,
"cookies": false,
"type": "",
@ -814,7 +829,7 @@
}
},
"put": {
"summary": "Create MFA challenge (confirmation)",
"summary": "Update MFA challenge (confirmation)",
"operationId": "accountUpdateMfaChallenge",
"tags": [
"account"
@ -834,6 +849,7 @@
},
"x-appwrite": {
"method": "updateMfaChallenge",
"group": "mfa",
"weight": 54,
"cookies": false,
"type": "",
@ -909,6 +925,7 @@
},
"x-appwrite": {
"method": "listMfaFactors",
"group": "mfa",
"weight": 46,
"cookies": false,
"type": "",
@ -939,7 +956,7 @@
},
"\/account\/mfa\/recovery-codes": {
"get": {
"summary": "Get MFA recovery codes",
"summary": "List MFA recovery codes",
"operationId": "accountGetMfaRecoveryCodes",
"tags": [
"account"
@ -959,6 +976,7 @@
},
"x-appwrite": {
"method": "getMfaRecoveryCodes",
"group": "mfa",
"weight": 51,
"cookies": false,
"type": "",
@ -1007,6 +1025,7 @@
},
"x-appwrite": {
"method": "createMfaRecoveryCodes",
"group": "mfa",
"weight": 49,
"cookies": false,
"type": "",
@ -1035,7 +1054,7 @@
]
},
"patch": {
"summary": "Regenerate MFA recovery codes",
"summary": "Update MFA recovery codes (regenerate)",
"operationId": "accountUpdateMfaRecoveryCodes",
"tags": [
"account"
@ -1055,6 +1074,7 @@
},
"x-appwrite": {
"method": "updateMfaRecoveryCodes",
"group": "mfa",
"weight": 50,
"cookies": false,
"type": "",
@ -1105,6 +1125,7 @@
},
"x-appwrite": {
"method": "updateName",
"group": "account",
"weight": 33,
"cookies": false,
"type": "",
@ -1174,6 +1195,7 @@
},
"x-appwrite": {
"method": "updatePassword",
"group": "account",
"weight": 34,
"cookies": false,
"type": "",
@ -1248,6 +1270,7 @@
},
"x-appwrite": {
"method": "updatePhone",
"group": "account",
"weight": 36,
"cookies": false,
"type": "",
@ -1323,6 +1346,7 @@
},
"x-appwrite": {
"method": "getPrefs",
"group": "account",
"weight": 31,
"cookies": false,
"type": "",
@ -1371,6 +1395,7 @@
},
"x-appwrite": {
"method": "updatePrefs",
"group": "account",
"weight": 37,
"cookies": false,
"type": "",
@ -1440,6 +1465,7 @@
},
"x-appwrite": {
"method": "createRecovery",
"group": "recovery",
"weight": 39,
"cookies": false,
"type": "",
@ -1496,7 +1522,7 @@
}
},
"put": {
"summary": "Create password recovery (confirmation)",
"summary": "Update password recovery (confirmation)",
"operationId": "accountUpdateRecovery",
"tags": [
"account"
@ -1516,6 +1542,7 @@
},
"x-appwrite": {
"method": "updateRecovery",
"group": "recovery",
"weight": 40,
"cookies": false,
"type": "",
@ -1597,6 +1624,7 @@
},
"x-appwrite": {
"method": "listSessions",
"group": "sessions",
"weight": 12,
"cookies": false,
"type": "",
@ -1638,6 +1666,7 @@
},
"x-appwrite": {
"method": "deleteSessions",
"group": "sessions",
"weight": 13,
"cookies": false,
"type": "",
@ -1688,6 +1717,7 @@
},
"x-appwrite": {
"method": "createAnonymousSession",
"group": "sessions",
"weight": 18,
"cookies": false,
"type": "",
@ -1736,6 +1766,7 @@
},
"x-appwrite": {
"method": "createEmailPasswordSession",
"group": "sessions",
"weight": 17,
"cookies": false,
"type": "",
@ -1809,6 +1840,7 @@
},
"x-appwrite": {
"method": "updateMagicURLSession",
"group": "sessions",
"weight": 27,
"cookies": false,
"type": "",
@ -1875,6 +1907,7 @@
},
"x-appwrite": {
"method": "createOAuth2Session",
"group": "sessions",
"weight": 20,
"cookies": false,
"type": "webAuth",
@ -1902,7 +1935,7 @@
"parameters": [
{
"name": "provider",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"required": true,
"schema": {
"type": "string",
@ -1922,6 +1955,7 @@
"dropbox",
"etsy",
"facebook",
"figma",
"github",
"gitlab",
"google",
@ -2015,6 +2049,7 @@
},
"x-appwrite": {
"method": "updatePhoneSession",
"group": "sessions",
"weight": 28,
"cookies": false,
"type": "",
@ -2088,6 +2123,7 @@
},
"x-appwrite": {
"method": "createSession",
"group": "sessions",
"weight": 19,
"cookies": false,
"type": "",
@ -2161,6 +2197,7 @@
},
"x-appwrite": {
"method": "getSession",
"group": "sessions",
"weight": 14,
"cookies": false,
"type": "",
@ -2221,6 +2258,7 @@
},
"x-appwrite": {
"method": "updateSession",
"group": "sessions",
"weight": 16,
"cookies": false,
"type": "",
@ -2274,6 +2312,7 @@
},
"x-appwrite": {
"method": "deleteSession",
"group": "sessions",
"weight": 15,
"cookies": false,
"type": "",
@ -2336,6 +2375,7 @@
},
"x-appwrite": {
"method": "updateStatus",
"group": "account",
"weight": 38,
"cookies": false,
"type": "",
@ -2386,6 +2426,7 @@
},
"x-appwrite": {
"method": "createPushTarget",
"group": "pushTargets",
"weight": 55,
"cookies": false,
"type": "",
@ -2464,6 +2505,7 @@
},
"x-appwrite": {
"method": "updatePushTarget",
"group": "pushTargets",
"weight": 56,
"cookies": false,
"type": "",
@ -2534,6 +2576,7 @@
},
"x-appwrite": {
"method": "deletePushTarget",
"group": "pushTargets",
"weight": 57,
"cookies": false,
"type": "",
@ -2594,6 +2637,7 @@
},
"x-appwrite": {
"method": "createEmailToken",
"group": "tokens",
"weight": 26,
"cookies": false,
"type": "",
@ -2672,6 +2716,7 @@
},
"x-appwrite": {
"method": "createMagicURLToken",
"group": "tokens",
"weight": 25,
"cookies": false,
"type": "",
@ -2751,6 +2796,7 @@
},
"x-appwrite": {
"method": "createOAuth2Token",
"group": "tokens",
"weight": 24,
"cookies": false,
"type": "webAuth",
@ -2778,7 +2824,7 @@
"parameters": [
{
"name": "provider",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
"required": true,
"schema": {
"type": "string",
@ -2798,6 +2844,7 @@
"dropbox",
"etsy",
"facebook",
"figma",
"github",
"gitlab",
"google",
@ -2891,6 +2938,7 @@
},
"x-appwrite": {
"method": "createPhoneToken",
"group": "tokens",
"weight": 29,
"cookies": false,
"type": "",
@ -2967,6 +3015,7 @@
},
"x-appwrite": {
"method": "createVerification",
"group": "verification",
"weight": 41,
"cookies": false,
"type": "",
@ -3014,7 +3063,7 @@
}
},
"put": {
"summary": "Create email verification (confirmation)",
"summary": "Update email verification (confirmation)",
"operationId": "accountUpdateVerification",
"tags": [
"account"
@ -3034,6 +3083,7 @@
},
"x-appwrite": {
"method": "updateVerification",
"group": "verification",
"weight": 42,
"cookies": false,
"type": "",
@ -3109,6 +3159,7 @@
},
"x-appwrite": {
"method": "createPhoneVerification",
"group": "verification",
"weight": 43,
"cookies": false,
"type": "",
@ -3160,6 +3211,7 @@
},
"x-appwrite": {
"method": "updatePhoneVerification",
"group": "verification",
"weight": 44,
"cookies": false,
"type": "",
@ -3228,6 +3280,7 @@
},
"x-appwrite": {
"method": "getBrowser",
"group": null,
"weight": 61,
"cookies": false,
"type": "location",
@ -3353,6 +3406,7 @@
},
"x-appwrite": {
"method": "getCreditCard",
"group": null,
"weight": 60,
"cookies": false,
"type": "location",
@ -3484,6 +3538,7 @@
},
"x-appwrite": {
"method": "getFavicon",
"group": null,
"weight": 64,
"cookies": false,
"type": "location",
@ -3541,6 +3596,7 @@
},
"x-appwrite": {
"method": "getFlag",
"group": null,
"weight": 62,
"cookies": false,
"type": "location",
@ -4028,6 +4084,7 @@
},
"x-appwrite": {
"method": "getImage",
"group": null,
"weight": 63,
"cookies": false,
"type": "location",
@ -4109,6 +4166,7 @@
},
"x-appwrite": {
"method": "getInitials",
"group": null,
"weight": 66,
"cookies": false,
"type": "location",
@ -4200,6 +4258,7 @@
},
"x-appwrite": {
"method": "getQR",
"group": null,
"weight": 65,
"cookies": false,
"type": "location",
@ -4298,6 +4357,7 @@
},
"x-appwrite": {
"method": "listDocuments",
"group": "documents",
"weight": 110,
"cookies": false,
"type": "",
@ -4382,6 +4442,7 @@
},
"x-appwrite": {
"method": "createDocument",
"group": "documents",
"weight": 109,
"cookies": false,
"type": "",
@ -4488,6 +4549,7 @@
},
"x-appwrite": {
"method": "getDocument",
"group": "documents",
"weight": 111,
"cookies": false,
"type": "",
@ -4582,6 +4644,7 @@
},
"x-appwrite": {
"method": "updateDocument",
"group": "documents",
"weight": 113,
"cookies": false,
"type": "",
@ -4680,6 +4743,7 @@
},
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 114,
"cookies": false,
"type": "",
@ -4763,7 +4827,8 @@
},
"x-appwrite": {
"method": "listExecutions",
"weight": 389,
"group": "executions",
"weight": 388,
"cookies": false,
"type": "",
"deprecated": false,
@ -4837,7 +4902,8 @@
},
"x-appwrite": {
"method": "createExecution",
"weight": 387,
"group": "executions",
"weight": 386,
"cookies": false,
"type": "",
"deprecated": false,
@ -4951,7 +5017,8 @@
},
"x-appwrite": {
"method": "getExecution",
"weight": 388,
"group": "executions",
"weight": 387,
"cookies": false,
"type": "",
"deprecated": false,
@ -5024,7 +5091,8 @@
},
"x-appwrite": {
"method": "query",
"weight": 303,
"group": "graphql",
"weight": 302,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5075,7 +5143,8 @@
},
"x-appwrite": {
"method": "mutation",
"weight": 302,
"group": "graphql",
"weight": 301,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5126,6 +5195,7 @@
},
"x-appwrite": {
"method": "get",
"group": null,
"weight": 118,
"cookies": false,
"type": "",
@ -5177,6 +5247,7 @@
},
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 119,
"cookies": false,
"type": "",
@ -5228,6 +5299,7 @@
},
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 123,
"cookies": false,
"type": "",
@ -5279,6 +5351,7 @@
},
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 120,
"cookies": false,
"type": "",
@ -5330,6 +5403,7 @@
},
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 121,
"cookies": false,
"type": "",
@ -5381,6 +5455,7 @@
},
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 122,
"cookies": false,
"type": "",
@ -5432,6 +5507,7 @@
},
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 124,
"cookies": false,
"type": "",
@ -5483,6 +5559,7 @@
},
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 125,
"cookies": false,
"type": "",
@ -5534,7 +5611,8 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 349,
"group": "subscribers",
"weight": 348,
"cookies": false,
"type": "",
"deprecated": false,
@ -5616,7 +5694,8 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 353,
"group": "subscribers",
"weight": 352,
"cookies": false,
"type": "",
"deprecated": false,
@ -5690,7 +5769,8 @@
},
"x-appwrite": {
"method": "listFiles",
"weight": 209,
"group": "files",
"weight": 208,
"cookies": false,
"type": "",
"deprecated": false,
@ -5775,7 +5855,8 @@
},
"x-appwrite": {
"method": "createFile",
"weight": 208,
"group": "files",
"weight": 207,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -5872,7 +5953,8 @@
},
"x-appwrite": {
"method": "getFile",
"weight": 210,
"group": "files",
"weight": 209,
"cookies": false,
"type": "",
"deprecated": false,
@ -5943,7 +6025,8 @@
},
"x-appwrite": {
"method": "updateFile",
"weight": 215,
"group": "files",
"weight": 214,
"cookies": false,
"type": "",
"deprecated": false,
@ -6031,7 +6114,8 @@
},
"x-appwrite": {
"method": "deleteFile",
"weight": 216,
"group": "files",
"weight": 215,
"cookies": false,
"type": "",
"deprecated": false,
@ -6097,7 +6181,8 @@
},
"x-appwrite": {
"method": "getFileDownload",
"weight": 212,
"group": "files",
"weight": 211,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6163,7 +6248,8 @@
},
"x-appwrite": {
"method": "getFilePreview",
"weight": 211,
"group": "files",
"weight": 210,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6379,7 +6465,8 @@
},
"x-appwrite": {
"method": "getFileView",
"weight": 213,
"group": "files",
"weight": 212,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6452,7 +6539,8 @@
},
"x-appwrite": {
"method": "list",
"weight": 220,
"group": "teams",
"weight": 219,
"cookies": false,
"type": "",
"deprecated": false,
@ -6527,7 +6615,8 @@
},
"x-appwrite": {
"method": "create",
"weight": 219,
"group": "teams",
"weight": 218,
"cookies": false,
"type": "",
"deprecated": false,
@ -6611,7 +6700,8 @@
},
"x-appwrite": {
"method": "get",
"weight": 221,
"group": "teams",
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -6672,7 +6762,8 @@
},
"x-appwrite": {
"method": "updateName",
"weight": 223,
"group": "teams",
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,
@ -6745,7 +6836,8 @@
},
"x-appwrite": {
"method": "delete",
"weight": 225,
"group": "teams",
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -6808,7 +6900,8 @@
},
"x-appwrite": {
"method": "listMemberships",
"weight": 227,
"group": "memberships",
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -6893,7 +6986,8 @@
},
"x-appwrite": {
"method": "createMembership",
"weight": 226,
"group": "memberships",
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -7003,7 +7097,8 @@
},
"x-appwrite": {
"method": "getMembership",
"weight": 228,
"group": "memberships",
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7074,7 +7169,8 @@
},
"x-appwrite": {
"method": "updateMembership",
"weight": 229,
"group": "memberships",
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -7160,7 +7256,8 @@
},
"x-appwrite": {
"method": "deleteMembership",
"weight": 231,
"group": "memberships",
"weight": 230,
"cookies": false,
"type": "",
"deprecated": false,
@ -7233,7 +7330,8 @@
},
"x-appwrite": {
"method": "updateMembershipStatus",
"weight": 230,
"group": "memberships",
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7330,7 +7428,8 @@
},
"x-appwrite": {
"method": "getPrefs",
"weight": 222,
"group": "teams",
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -7390,7 +7489,8 @@
},
"x-appwrite": {
"method": "updatePrefs",
"weight": 224,
"group": "teams",
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -7471,7 +7571,8 @@
},
"x-appwrite": {
"method": "list",
"weight": 432,
"group": "files",
"weight": 436,
"cookies": false,
"type": "",
"deprecated": false,
@ -7552,7 +7653,8 @@
},
"x-appwrite": {
"method": "createFileToken",
"weight": 429,
"group": "files",
"weight": 433,
"cookies": false,
"type": "",
"deprecated": false,
@ -7650,7 +7752,8 @@
},
"x-appwrite": {
"method": "get",
"weight": 430,
"group": "tokens",
"weight": 434,
"cookies": false,
"type": "",
"deprecated": false,
@ -7711,7 +7814,8 @@
},
"x-appwrite": {
"method": "update",
"weight": 433,
"group": "tokens",
"weight": 437,
"cookies": false,
"type": "",
"deprecated": false,
@ -7790,7 +7894,8 @@
},
"x-appwrite": {
"method": "delete",
"weight": 434,
"group": "tokens",
"weight": 438,
"cookies": false,
"type": "",
"deprecated": false,
@ -7853,7 +7958,8 @@
},
"x-appwrite": {
"method": "getJWT",
"weight": 431,
"group": "tokens",
"weight": 435,
"cookies": false,
"type": "",
"deprecated": false,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -183,13 +183,15 @@ return [
'variables' => []
],
[
'key' => 'lynx-starter',
'name' => 'Lynx Starter',
'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.',
'key' => 'playground-for-lynx',
'name' => 'Lynx playground',
'tagline' => 'A basic Lynx website without Appwrite SDK integration.',
// When we add Lynx with Appwrite SDK, use following tagline for it:
// 'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/lynx-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/lynx-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-lynx-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-lynx-light.png',
'frameworks' => [
getFramework('LYNX', [
'providerRootDirectory' => './lynx/starter',
@ -1108,15 +1110,14 @@ return [
'providerVersion' => '0.1.*',
'variables' => []
],
// TODO: Remove astro starter eventually, or add all frameworks's starters
[
'key' => 'astro-starter',
'name' => 'Astro starter',
'tagline' => 'Sample application built with Astro, a content-driven web framework.',
'key' => 'playground-for-astro',
'name' => 'Astro playground',
'tagline' => 'A basic Astro website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/astro-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-astro-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-astro-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/starter',
@ -1125,17 +1126,17 @@ return [
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'remix-starter',
'name' => 'Remix starter',
'tagline' => 'Sample application built with Remix, a React meta-framework.',
'key' => 'playground-for-remix',
'name' => 'Remix playground',
'tagline' => 'A basic Remix website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/remix-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-remix-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-remix-light.png',
'frameworks' => [
getFramework('REMIX', [
'providerRootDirectory' => './remix/starter',
@ -1144,7 +1145,201 @@ return [
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-nextjs',
'name' => 'Next.js playground',
'tagline' => 'A basic Next.js website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-nextjs-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-nextjs-light.png',
'frameworks' => [
getFramework('NEXTJS', [
'providerRootDirectory' => './nextjs/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-flutter',
'name' => 'Flutter playground',
'tagline' => 'A basic Flutter website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-flutter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-flutter-light.png',
'frameworks' => [
getFramework('FLUTTER', [
'providerRootDirectory' => './flutter/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-vite',
'name' => 'Vite playground',
'tagline' => 'A basic Vite website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-vite-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-vite-light.png',
'frameworks' => [
getFramework('VITE', [
'providerRootDirectory' => './vite/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-angular',
'name' => 'Angular playground',
'tagline' => 'A basic Angular website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-angular-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-angular-light.png',
'frameworks' => [
getFramework('ANGULAR', [
'providerRootDirectory' => './angular/starter',
'outputDirectory' => './dist/starter/browser',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-analog',
'name' => 'Analog playground',
'tagline' => 'A basic Analog website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-analog-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-analog-light.png',
'frameworks' => [
getFramework('ANALOG', [
'providerRootDirectory' => './analog/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-svelte',
'name' => 'Svelte playground',
'tagline' => 'A basic Svelte website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-svelte-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-svelte-light.png',
'frameworks' => [
getFramework('SVELTEKIT', [
'providerRootDirectory' => './sveltekit/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-react',
'name' => 'React playground',
'tagline' => 'A basic React website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-react-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-react-light.png',
'frameworks' => [
getFramework('REACT', [
'outputDirectory' => './build',
'providerRootDirectory' => './react/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-vue',
'name' => 'Vue playground',
'tagline' => 'A basic Vue website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-vue-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-vue-light.png',
'frameworks' => [
getFramework('VUE', [
'providerRootDirectory' => './vue/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-nuxt',
'name' => 'Nuxt playground',
'tagline' => 'A basic Nuxt website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-nuxt-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-nuxt-light.png',
'frameworks' => [
getFramework('NUXT', [
'providerRootDirectory' => './nuxt/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-react-native',
'name' => 'React Native playground',
'tagline' => 'A basic React Native website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-react-native-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-react-native-light.png',
'frameworks' => [
getFramework('REACT', [
'providerRootDirectory' => './react-native/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
];

View file

@ -88,6 +88,15 @@ return [
'question' => 'Enter your Appwrite hostname',
'filter' => ''
],
[
'name' => '_APP_CUSTOM_DOMAIN_DENY_LIST',
'description' => 'List of reserved or prohibited domains when configuring custom domains.',
'introduction' => '',
'default' => 'example.com,test.com,app.example.com',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_FUNCTIONS',
'description' => 'A domain to use for function preview URLs. Setting to empty turns off function preview URLs.',

View file

@ -43,6 +43,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -155,9 +156,6 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc
$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) {
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
/** @var Utopia\Database\Document $user */
$userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId));
@ -273,7 +271,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res
->setAttribute('current', true)
->setAttribute('countryName', $countryName)
->setAttribute('expire', $expire)
->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $sessionSecret) : '')
->setAttribute('secret', Auth::encodeSession($user->getId(), $sessionSecret))
;
$response->dynamic($session, Response::MODEL_SESSION);
@ -289,6 +287,7 @@ App::post('/v1/account')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'create',
description: '/docs/references/account/create.md',
auth: [],
@ -432,6 +431,7 @@ App::get('/v1/account')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'get',
description: '/docs/references/account/get.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -461,6 +461,7 @@ App::delete('/v1/account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'delete',
description: '/docs/references/account/delete.md',
auth: [AuthType::ADMIN],
@ -513,6 +514,7 @@ App::get('/v1/account/sessions')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'listSessions',
description: '/docs/references/account/list-sessions.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -530,9 +532,6 @@ App::get('/v1/account/sessions')
->inject('project')
->action(function (Response $response, Document $user, Locale $locale, Document $project) {
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$sessions = $user->getAttribute('sessions', []);
$current = Auth::sessionVerify($sessions, Auth::$secret);
@ -542,7 +541,7 @@ App::get('/v1/account/sessions')
$session->setAttribute('countryName', $countryName);
$session->setAttribute('current', ($current == $session->getId()) ? true : false);
$session->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $session->getAttribute('secret', '') : '');
$session->setAttribute('secret', $session->getAttribute('secret', ''));
$sessions[$key] = $session;
}
@ -562,6 +561,7 @@ App::delete('/v1/account/sessions')
->label('audits.resource', 'user/{user.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'deleteSessions',
description: '/docs/references/account/delete-sessions.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -631,6 +631,7 @@ App::get('/v1/account/sessions/:sessionId')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'getSession',
description: '/docs/references/account/get-session.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -649,10 +650,6 @@ App::get('/v1/account/sessions/:sessionId')
->inject('project')
->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Document $project) {
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$sessions = $user->getAttribute('sessions', []);
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
@ -665,7 +662,7 @@ App::get('/v1/account/sessions/:sessionId')
$session
->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret)))
->setAttribute('countryName', $countryName)
->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $session->getAttribute('secret', '') : '')
->setAttribute('secret', $session->getAttribute('secret', ''))
;
return $response->dynamic($session, Response::MODEL_SESSION);
@ -684,6 +681,7 @@ App::delete('/v1/account/sessions/:sessionId')
->label('audits.resource', 'user/{user.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'deleteSession',
description: '/docs/references/account/delete-session.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -772,6 +770,7 @@ App::patch('/v1/account/sessions/:sessionId')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'updateSession',
description: '/docs/references/account/update-session.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -856,6 +855,7 @@ App::post('/v1/account/sessions/email')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'createEmailPasswordSession',
description: '/docs/references/account/create-session-email-password.md',
auth: [],
@ -897,10 +897,6 @@ App::post('/v1/account/sessions/email')
throw new Exception(Exception::USER_BLOCKED); // User is in status blocked
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$user->setAttributes($profile->getArrayCopy());
$hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]);
@ -966,7 +962,7 @@ App::post('/v1/account/sessions/email')
$session
->setAttribute('current', true)
->setAttribute('countryName', $countryName)
->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : '')
->setAttribute('secret', Auth::encodeSession($user->getId(), $secret))
;
$queueForEvents
@ -996,6 +992,7 @@ App::post('/v1/account/sessions/anonymous')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'createAnonymousSession',
description: '/docs/references/account/create-session-anonymous.md',
auth: [],
@ -1019,9 +1016,6 @@ App::post('/v1/account/sessions/anonymous')
->inject('queueForEvents')
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) {
$protocol = $request->getProtocol();
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
if ('console' === $project->getId()) {
throw new Exception(Exception::USER_ANONYMOUS_CONSOLE_PROHIBITED, 'Failed to create anonymous user');
@ -1123,7 +1117,7 @@ App::post('/v1/account/sessions/anonymous')
$session
->setAttribute('current', true)
->setAttribute('countryName', $countryName)
->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : '')
->setAttribute('secret', Auth::encodeSession($user->getId(), $secret))
;
$response->dynamic($session, Response::MODEL_SESSION);
@ -1139,6 +1133,7 @@ App::post('/v1/account/sessions/token')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'createSession',
description: '/docs/references/account/create-session.md',
auth: [],
@ -1172,6 +1167,7 @@ App::get('/v1/account/sessions/oauth2/:provider')
->label('scope', 'sessions.write')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'createOAuth2Session',
description: '/docs/references/account/create-session-oauth2.md',
type: MethodType::WEBAUTH,
@ -1243,7 +1239,7 @@ App::get('/v1/account/sessions/oauth2/:provider')
});
App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 callback')
->desc('Get OAuth2 callback')
->groups(['account'])
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('scope', 'public')
@ -1273,7 +1269,7 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
});
App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 callback')
->desc('Create OAuth2 callback')
->groups(['account'])
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('scope', 'public')
@ -1304,7 +1300,7 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
});
App::get('/v1/account/sessions/oauth2/:provider/redirect')
->desc('OAuth2 redirect')
->desc('Get OAuth2 redirect')
->groups(['api', 'account', 'session'])
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('event', 'users.[userId].sessions.[sessionId].create')
@ -1449,7 +1445,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::notEqual('userInternalId', $user->getInternalId()),
]);
if (!$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_ALREADY_EXISTS);
$failureRedirect(Exception::USER_ALREADY_EXISTS);
}
$userWithMatchingEmail = $dbForProject->find('users', [
@ -1457,7 +1453,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::notEqual('$id', $userId),
]);
if (!empty($userWithMatchingEmail)) {
throw new Exception(Exception::USER_ALREADY_EXISTS);
$failureRedirect(Exception::USER_ALREADY_EXISTS);
}
$sessionUpgrade = true;
@ -1486,7 +1482,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
if ($user === false || $user->isEmpty()) { // No user logged in or with OAuth2 provider ID, create new one or connect with account with same email
if (empty($email)) {
throw new Exception(Exception::USER_UNAUTHORIZED, 'OAuth provider failed to return email.');
$failureRedirect(Exception::USER_UNAUTHORIZED, 'OAuth provider failed to return email.');
}
/**
@ -1529,7 +1525,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::equal('providerEmail', [$email]),
]);
if (!$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
$failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
try {
@ -1601,7 +1597,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::notEqual('userInternalId', $user->getInternalId()),
]);
if (!empty($identitiesWithMatchingEmail)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
$failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
$dbForProject->createDocument('identities', new Document([
@ -1769,6 +1765,7 @@ App::get('/v1/account/tokens/oauth2/:provider')
->label('scope', 'sessions.write')
->label('sdk', new Method(
namespace: 'account',
group: 'tokens',
name: 'createOAuth2Token',
description: '/docs/references/account/create-token-oauth2.md',
auth: [],
@ -1849,6 +1846,7 @@ App::post('/v1/account/tokens/magic-url')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'tokens',
name: 'createMagicURLToken',
description: '/docs/references/account/create-token-magic-url.md',
auth: [],
@ -1884,9 +1882,6 @@ App::post('/v1/account/tokens/magic-url')
$phrase = Phrase::generate();
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$result = $dbForProject->findOne('users', [Query::equal('email', [$email])]);
if (!$result->isEmpty()) {
@ -2068,17 +2063,11 @@ App::post('/v1/account/tokens/magic-url')
->setRecipient($email)
->trigger();
// Set to unhashed secret for events and server responses
$token->setAttribute('secret', $tokenSecret);
$queueForEvents
->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
if (!$isPrivilegedUser && !$isAppUser) {
$token->setAttribute('secret', '');
}
if (!empty($phrase)) {
$token->setAttribute('phrase', $phrase);
}
@ -2098,6 +2087,7 @@ App::post('/v1/account/tokens/email')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'tokens',
name: 'createEmailToken',
description: '/docs/references/account/create-token-email.md',
auth: [],
@ -2131,10 +2121,6 @@ App::post('/v1/account/tokens/email')
$phrase = Phrase::generate();
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$result = $dbForProject->findOne('users', [Query::equal('email', [$email])]);
if (!$result->isEmpty()) {
$user->setAttributes($result->getArrayCopy());
@ -2303,17 +2289,11 @@ App::post('/v1/account/tokens/email')
->setRecipient($email)
->trigger();
// Set to unhashed secret for events and server responses
$token->setAttribute('secret', $tokenSecret);
$queueForEvents
->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
if (!$isPrivilegedUser && !$isAppUser) {
$token->setAttribute('secret', '');
}
if (!empty($phrase)) {
$token->setAttribute('phrase', $phrase);
}
@ -2333,6 +2313,7 @@ App::put('/v1/account/sessions/magic-url')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'updateMagicURLSession',
description: '/docs/references/account/create-session.md',
auth: [],
@ -2370,6 +2351,7 @@ App::put('/v1/account/sessions/phone')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'sessions',
name: 'updatePhoneSession',
description: '/docs/references/account/create-session.md',
auth: [],
@ -2408,6 +2390,7 @@ App::post('/v1/account/tokens/phone')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'tokens',
name: 'createPhoneToken',
description: '/docs/references/account/create-token-phone.md',
auth: [],
@ -2439,10 +2422,6 @@ App::post('/v1/account/tokens/phone')
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$result = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]);
if (!$result->isEmpty()) {
$user->setAttributes($result->getArrayCopy());
@ -2594,14 +2573,13 @@ App::post('/v1/account/tokens/phone')
}
}
// Set to unhashed secret for events and server responses
$token->setAttribute('secret', $secret);
$queueForEvents
->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : '');
// Encode secret for clients
$token->setAttribute('secret', Auth::encodeSession($user->getId(), $secret));
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@ -2616,6 +2594,7 @@ App::post('/v1/account/jwts')
->label('auth.type', 'jwt')
->label('sdk', new Method(
namespace: 'account',
group: 'tokens',
name: 'createJWT',
description: '/docs/references/account/create-jwt.md',
auth: [],
@ -2664,6 +2643,7 @@ App::get('/v1/account/prefs')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'getPrefs',
description: '/docs/references/account/get-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -2690,6 +2670,7 @@ App::get('/v1/account/logs')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'logs',
name: 'listLogs',
description: '/docs/references/account/list-logs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -2766,6 +2747,7 @@ App::patch('/v1/account/name')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updateName',
description: '/docs/references/account/update-name.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -2804,6 +2786,7 @@ App::patch('/v1/account/password')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updatePassword',
description: '/docs/references/account/update-password.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -2877,6 +2860,7 @@ App::patch('/v1/account/email')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updateEmail',
description: '/docs/references/account/update-email.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -2973,6 +2957,7 @@ App::patch('/v1/account/phone')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updatePhone',
description: '/docs/references/account/update-phone.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3058,6 +3043,7 @@ App::patch('/v1/account/prefs')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updatePrefs',
description: '/docs/references/account/update-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3095,6 +3081,7 @@ App::patch('/v1/account/status')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'account',
name: 'updateStatus',
description: '/docs/references/account/update-status.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3145,6 +3132,7 @@ App::post('/v1/account/recovery')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'recovery',
name: 'createRecovery',
description: '/docs/references/account/create-recovery.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3174,11 +3162,6 @@ App::post('/v1/account/recovery')
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
}
$url = htmlentities($url);
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$email = \strtolower($email);
$profile = $dbForProject->findOne('users', [
@ -3302,19 +3285,13 @@ App::post('/v1/account/recovery')
->setSubject($subject)
->trigger();
// Set to unhashed secret for events and server responses
$recovery->setAttribute('secret', $secret);
$queueForEvents
->setParam('userId', $profile->getId())
->setParam('tokenId', $recovery->getId())
->setUser($profile)
->setPayload($response->output($recovery, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
if (!$isPrivilegedUser && !$isAppUser) {
$recovery->setAttribute('secret', '');
}
->setPayload(Response::showSensitive(fn () => $response->output($recovery, Response::MODEL_TOKEN)), sensitive: ['secret']);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@ -3322,7 +3299,7 @@ App::post('/v1/account/recovery')
});
App::put('/v1/account/recovery')
->desc('Create password recovery (confirmation)')
->desc('Update password recovery (confirmation)')
->groups(['api', 'account'])
->label('scope', 'sessions.write')
->label('event', 'users.[userId].recovery.[tokenId].update')
@ -3331,6 +3308,7 @@ App::put('/v1/account/recovery')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'recovery',
name: 'updateRecovery',
description: '/docs/references/account/update-recovery.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3407,7 +3385,7 @@ App::put('/v1/account/recovery')
$queueForEvents
->setParam('userId', $profile->getId())
->setParam('tokenId', $recoveryDocument->getId())
;
->setPayload(Response::showSensitive(fn () => $response->output($recoveryDocument, Response::MODEL_TOKEN)), sensitive: ['secret']);
$response->dynamic($recoveryDocument, Response::MODEL_TOKEN);
});
@ -3421,6 +3399,7 @@ App::post('/v1/account/verification')
->label('audits.resource', 'user/{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'verification',
name: 'createVerification',
description: '/docs/references/account/create-email-verification.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3454,9 +3433,6 @@ App::post('/v1/account/verification')
throw new Exception(Exception::USER_EMAIL_ALREADY_VERIFIED);
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$verificationSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_VERIFICATION);
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM);
@ -3565,18 +3541,12 @@ App::post('/v1/account/verification')
->setName($user->getAttribute('name') ?? '')
->trigger();
// Set to unhashed secret for events and server responses
$verification->setAttribute('secret', $verificationSecret);
$queueForEvents
->setParam('userId', $user->getId())
->setParam('tokenId', $verification->getId())
->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
if (!$isPrivilegedUser && !$isAppUser) {
$verification->setAttribute('secret', '');
}
->setPayload(Response::showSensitive(fn () => $response->output($verification, Response::MODEL_TOKEN)), sensitive: ['secret']);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@ -3584,7 +3554,7 @@ App::post('/v1/account/verification')
});
App::put('/v1/account/verification')
->desc('Create email verification (confirmation)')
->desc('Update email verification (confirmation)')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].verification.[tokenId].update')
@ -3592,6 +3562,7 @@ App::put('/v1/account/verification')
->label('audits.resource', 'user/{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'verification',
name: 'updateVerification',
description: '/docs/references/account/update-email-verification.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3643,7 +3614,8 @@ App::put('/v1/account/verification')
$queueForEvents
->setParam('userId', $userId)
->setParam('tokenId', $verification->getId());
->setParam('tokenId', $verification->getId())
->setPayload(Response::showSensitive(fn () => $response->output($verification, Response::MODEL_TOKEN)), sensitive: ['secret']);
$response->dynamic($verification, Response::MODEL_TOKEN);
});
@ -3658,6 +3630,7 @@ App::post('/v1/account/verification/phone')
->label('audits.resource', 'user/{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'verification',
name: 'createPhoneVerification',
description: '/docs/references/account/create-phone-verification.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3696,10 +3669,6 @@ App::post('/v1/account/verification/phone')
throw new Exception(Exception::USER_PHONE_ALREADY_VERIFIED);
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$secret = null;
$sendSMS = true;
$mockNumbers = $project->getAttribute('auths', [])['mockNumbers'] ?? [];
@ -3788,7 +3757,6 @@ App::post('/v1/account/verification/phone')
}
}
// Set to unhashed secret for events and server responses
$verification->setAttribute('secret', $secret);
$queueForEvents
@ -3796,11 +3764,6 @@ App::post('/v1/account/verification/phone')
->setParam('tokenId', $verification->getId())
->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']);
// Hide secret for clients
if (!$isPrivilegedUser && !$isAppUser) {
$verification->setAttribute('secret', '');
}
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($verification, Response::MODEL_TOKEN);
@ -3815,6 +3778,7 @@ App::put('/v1/account/verification/phone')
->label('audits.resource', 'user/{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'verification',
name: 'updatePhoneVerification',
description: '/docs/references/account/update-phone-verification.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3880,6 +3844,7 @@ App::patch('/v1/account/mfa')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'updateMFA',
description: '/docs/references/account/update-mfa.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3933,6 +3898,7 @@ App::get('/v1/account/mfa/factors')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'listMfaFactors',
description: '/docs/references/account/list-mfa-factors.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -3973,6 +3939,7 @@ App::post('/v1/account/mfa/authenticators/:type')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'createMfaAuthenticator',
description: '/docs/references/account/create-mfa-authenticator.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4040,7 +4007,7 @@ App::post('/v1/account/mfa/authenticators/:type')
});
App::put('/v1/account/mfa/authenticators/:type')
->desc('Verify authenticator')
->desc('Update authenticator (confirmation)')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.mfa')
->label('scope', 'account')
@ -4049,6 +4016,7 @@ App::put('/v1/account/mfa/authenticators/:type')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'updateMfaAuthenticator',
description: '/docs/references/account/update-mfa-authenticator.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4118,6 +4086,7 @@ App::post('/v1/account/mfa/recovery-codes')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'createMfaRecoveryCodes',
description: '/docs/references/account/create-mfa-recovery-codes.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4155,7 +4124,7 @@ App::post('/v1/account/mfa/recovery-codes')
});
App::patch('/v1/account/mfa/recovery-codes')
->desc('Regenerate MFA recovery codes')
->desc('Update MFA recovery codes (regenerate)')
->groups(['api', 'account', 'mfaProtected'])
->label('event', 'users.[userId].update.mfa')
->label('scope', 'account')
@ -4164,6 +4133,7 @@ App::patch('/v1/account/mfa/recovery-codes')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'updateMfaRecoveryCodes',
description: '/docs/references/account/update-mfa-recovery-codes.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4200,11 +4170,12 @@ App::patch('/v1/account/mfa/recovery-codes')
});
App::get('/v1/account/mfa/recovery-codes')
->desc('Get MFA recovery codes')
->desc('List MFA recovery codes')
->groups(['api', 'account', 'mfaProtected'])
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'getMfaRecoveryCodes',
description: '/docs/references/account/get-mfa-recovery-codes.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4243,6 +4214,7 @@ App::delete('/v1/account/mfa/authenticators/:type')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'deleteMfaAuthenticator',
description: '/docs/references/account/delete-mfa-authenticator.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4288,6 +4260,7 @@ App::post('/v1/account/mfa/challenge')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'createMfaChallenge',
description: '/docs/references/account/create-mfa-challenge.md',
auth: [],
@ -4498,7 +4471,7 @@ App::post('/v1/account/mfa/challenge')
});
App::put('/v1/account/mfa/challenge')
->desc('Create MFA challenge (confirmation)')
->desc('Update MFA challenge (confirmation)')
->groups(['api', 'account', 'mfa'])
->label('scope', 'account')
->label('event', 'users.[userId].sessions.[sessionId].create')
@ -4507,6 +4480,7 @@ App::put('/v1/account/mfa/challenge')
->label('audits.userId', '{response.userId}')
->label('sdk', new Method(
namespace: 'account',
group: 'mfa',
name: 'updateMfaChallenge',
description: '/docs/references/account/update-mfa-challenge.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4600,6 +4574,7 @@ App::post('/v1/account/targets/push')
->label('event', 'users.[userId].targets.[targetId].create')
->label('sdk', new Method(
namespace: 'account',
group: 'pushTargets',
name: 'createPushTarget',
description: '/docs/references/account/create-push-target.md',
auth: [AuthType::SESSION],
@ -4680,6 +4655,7 @@ App::put('/v1/account/targets/:targetId/push')
->label('event', 'users.[userId].targets.[targetId].update')
->label('sdk', new Method(
namespace: 'account',
group: 'pushTargets',
name: 'updatePushTarget',
description: '/docs/references/account/update-push-target.md',
auth: [AuthType::SESSION],
@ -4744,6 +4720,7 @@ App::delete('/v1/account/targets/:targetId/push')
->label('event', 'users.[userId].targets.[targetId].delete')
->label('sdk', new Method(
namespace: 'account',
group: 'pushTargets',
name: 'deletePushTarget',
description: '/docs/references/account/delete-push-target.md',
auth: [AuthType::SESSION],
@ -4794,6 +4771,7 @@ App::get('/v1/account/identities')
->label('scope', 'account')
->label('sdk', new Method(
namespace: 'account',
group: 'identities',
name: 'listIdentities',
description: '/docs/references/account/list-identities.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -4845,8 +4823,11 @@ App::get('/v1/account/identities')
}
$filterQueries = Query::groupByType($queries)['filters'];
$results = $dbForProject->find('identities', $queries);
try {
$results = $dbForProject->find('identities', $queries);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT);
$response->dynamic(new Document([
@ -4865,6 +4846,7 @@ App::delete('/v1/account/identities/:identityId')
->label('audits.userId', '{user.$id}')
->label('sdk', new Method(
namespace: 'account',
group: 'identities',
name: 'deleteIdentity',
description: '/docs/references/account/delete-identity.md',
auth: [AuthType::SESSION, AuthType::JWT],

View file

@ -171,6 +171,7 @@ App::get('/v1/avatars/credit-cards/:code')
->label('cache.resource', 'avatar/credit-card')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getCreditCard',
description: '/docs/references/avatars/get-credit-card.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -198,6 +199,7 @@ App::get('/v1/avatars/browsers/:code')
->label('cache.resource', 'avatar/browser')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getBrowser',
description: '/docs/references/avatars/get-browser.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -225,6 +227,7 @@ App::get('/v1/avatars/flags/:code')
->label('cache.resource', 'avatar/flag')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getFlag',
description: '/docs/references/avatars/get-flag.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -252,6 +255,7 @@ App::get('/v1/avatars/image')
->label('cache.resource', 'avatar/image')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getImage',
description: '/docs/references/avatars/get-image.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -322,6 +326,7 @@ App::get('/v1/avatars/favicon')
->label('cache.resource', 'avatar/favicon')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getFavicon',
description: '/docs/references/avatars/get-favicon.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -472,6 +477,7 @@ App::get('/v1/avatars/qr')
->label('scope', 'avatars.read')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getQR',
description: '/docs/references/avatars/get-qr.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -521,6 +527,7 @@ App::get('/v1/avatars/initials')
->label('cache.resource', 'avatar/initials')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getInitials',
description: '/docs/references/avatars/get-initials.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],

View file

@ -29,6 +29,7 @@ App::get('/v1/console/variables')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'console',
group: 'console',
name: 'variables',
description: '/docs/references/console/variables.md',
auth: [AuthType::ADMIN],
@ -86,11 +87,12 @@ App::get('/v1/console/variables')
});
App::post('/v1/console/assistant')
->desc('Ask query')
->desc('Create assistant query')
->groups(['api', 'assistant'])
->label('scope', 'assistant.read')
->label('sdk', new Method(
namespace: 'assistant',
group: 'console',
name: 'chat',
description: '/docs/references/assistant/chat.md',
auth: [AuthType::ADMIN],

View file

@ -31,6 +31,7 @@ use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Index as IndexException;
use Utopia\Database\Exception\Limit as LimitException;
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Exception\Restricted as RestrictedException;
use Utopia\Database\Exception\Structure as StructureException;
@ -466,6 +467,7 @@ App::post('/v1/databases')
->label('audits.resource', 'database/{response.$id}')
->label('sdk', new Method(
namespace: 'databases',
group: 'databases',
name: 'create',
description: '/docs/references/databases/create.md',
auth: [AuthType::KEY],
@ -534,7 +536,6 @@ App::post('/v1/databases')
}
$queueForEvents->setParam('databaseId', $database->getId());
$queueForStatsUsage->addMetric(str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE), 1); // per database
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@ -548,6 +549,7 @@ App::get('/v1/databases')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'databases',
name: 'list',
description: '/docs/references/databases/list.md',
auth: [AuthType::KEY],
@ -597,9 +599,15 @@ App::get('/v1/databases')
$filterQueries = Query::groupByType($queries)['filters'];
try {
$databases = $dbForProject->find('databases', $queries);
$total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'databases' => $dbForProject->find('databases', $queries),
'total' => $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT),
'databases' => $databases,
'total' => $total,
]), Response::MODEL_DATABASE_LIST);
});
@ -610,6 +618,7 @@ App::get('/v1/databases/:databaseId')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'databases',
name: 'get',
description: '/docs/references/databases/get.md',
auth: [AuthType::KEY],
@ -642,6 +651,7 @@ App::get('/v1/databases/:databaseId/logs')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'logs',
name: 'listLogs',
description: '/docs/references/databases/get-logs.md',
auth: [AuthType::ADMIN],
@ -745,6 +755,7 @@ App::put('/v1/databases/:databaseId')
->label('audits.resource', 'database/{response.$id}')
->label('sdk', new Method(
namespace: 'databases',
group: 'databases',
name: 'update',
description: '/docs/references/databases/update.md',
auth: [AuthType::KEY],
@ -790,6 +801,7 @@ App::delete('/v1/databases/:databaseId')
->label('audits.resource', 'database/{request.databaseId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'databases',
name: 'delete',
description: '/docs/references/databases/delete.md',
auth: [AuthType::KEY],
@ -830,9 +842,6 @@ App::delete('/v1/databases/:databaseId')
->setParam('databaseId', $database->getId())
->setPayload($response->output($database, Response::MODEL_DATABASE));
$queueForStatsUsage
->addMetric(METRIC_DATABASES_STORAGE, 1); // Global, deletion forces full recalculation
$response->noContent();
});
@ -846,6 +855,7 @@ App::post('/v1/databases/:databaseId/collections')
->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}')
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'createCollection',
description: '/docs/references/databases/create-collection.md',
auth: [AuthType::KEY],
@ -917,6 +927,7 @@ App::get('/v1/databases/:databaseId/collections')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'listCollections',
description: '/docs/references/databases/list-collections.md',
auth: [AuthType::KEY],
@ -975,9 +986,15 @@ App::get('/v1/databases/:databaseId/collections')
$filterQueries = Query::groupByType($queries)['filters'];
try {
$collections = $dbForProject->find('database_' . $database->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries),
'total' => $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT),
'collections' => $collections,
'total' => $total,
]), Response::MODEL_COLLECTION_LIST);
});
@ -989,6 +1006,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'getCollection',
description: '/docs/references/databases/get-collection.md',
auth: [AuthType::KEY],
@ -1030,6 +1048,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'listCollectionLogs',
description: '/docs/references/databases/get-collection-logs.md',
auth: [AuthType::ADMIN],
@ -1142,6 +1161,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'updateCollection',
description: '/docs/references/databases/update-collection.md',
auth: [AuthType::KEY],
@ -1216,6 +1236,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'deleteCollection',
description: '/docs/references/databases/delete-collection.md',
auth: [AuthType::KEY],
@ -1279,6 +1300,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createStringAttribute',
description: '/docs/references/databases/create-string-attribute.md',
auth: [AuthType::KEY],
@ -1341,6 +1363,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createEmailAttribute',
description: '/docs/references/databases/create-email-attribute.md',
auth: [AuthType::KEY],
@ -1389,6 +1412,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createEnumAttribute',
description: '/docs/references/databases/create-attribute-enum.md',
auth: [AuthType::KEY],
@ -1442,6 +1466,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createIpAttribute',
description: '/docs/references/databases/create-ip-attribute.md',
auth: [AuthType::KEY],
@ -1490,6 +1515,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createUrlAttribute',
description: '/docs/references/databases/create-url-attribute.md',
auth: [AuthType::KEY],
@ -1538,6 +1564,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createIntegerAttribute',
description: '/docs/references/databases/create-integer-attribute.md',
auth: [AuthType::KEY],
@ -1615,6 +1642,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createFloatAttribute',
description: '/docs/references/databases/create-float-attribute.md',
auth: [AuthType::KEY],
@ -1690,6 +1718,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createBooleanAttribute',
description: '/docs/references/databases/create-boolean-attribute.md',
auth: [AuthType::KEY],
@ -1737,6 +1766,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createDatetimeAttribute',
description: '/docs/references/databases/create-datetime-attribute.md',
auth: [AuthType::KEY],
@ -1787,6 +1817,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'createRelationshipAttribute',
description: '/docs/references/databases/create-relationship-attribute.md',
auth: [AuthType::KEY],
@ -1918,6 +1949,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'listAttributes',
description: '/docs/references/databases/list-attributes.md',
auth: [AuthType::KEY],
@ -1986,9 +2018,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
}
$filters = Query::groupByType($queries)['filters'];
$attributes = $dbForProject->find('attributes', $queries);
$total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT);
try {
$attributes = $dbForProject->find('attributes', $queries);
$total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'attributes' => $attributes,
@ -2004,6 +2039,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'getAttribute',
description: '/docs/references/databases/get-attribute.md',
auth: [AuthType::KEY],
@ -2088,6 +2124,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateStringAttribute',
description: '/docs/references/databases/update-string-attribute.md',
auth: [AuthType::KEY],
@ -2139,6 +2176,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateEmailAttribute',
description: '/docs/references/databases/update-email-attribute.md',
auth: [AuthType::KEY],
@ -2188,6 +2226,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateEnumAttribute',
description: '/docs/references/databases/update-enum-attribute.md',
auth: [AuthType::KEY],
@ -2239,6 +2278,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:k
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateIpAttribute',
description: '/docs/references/databases/update-ip-attribute.md',
auth: [AuthType::KEY],
@ -2288,6 +2328,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/:
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateUrlAttribute',
description: '/docs/references/databases/update-url-attribute.md',
auth: [AuthType::KEY],
@ -2337,6 +2378,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateIntegerAttribute',
description: '/docs/references/databases/update-integer-attribute.md',
auth: [AuthType::KEY],
@ -2396,6 +2438,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateFloatAttribute',
description: '/docs/references/databases/update-float-attribute.md',
auth: [AuthType::KEY],
@ -2455,6 +2498,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boole
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateBooleanAttribute',
description: '/docs/references/databases/update-boolean-attribute.md',
auth: [AuthType::KEY],
@ -2503,6 +2547,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datet
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateDatetimeAttribute',
description: '/docs/references/databases/update-datetime-attribute.md',
auth: [AuthType::KEY],
@ -2551,6 +2596,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'updateRelationshipAttribute',
description: '/docs/references/databases/update-relationship-attribute.md',
auth: [AuthType::KEY],
@ -2616,6 +2662,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'attributes',
name: 'deleteAttribute',
description: '/docs/references/databases/delete-attribute.md',
auth: [AuthType::KEY],
@ -2732,9 +2779,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->setContext('database', $db)
->setPayload($response->output($attribute, $model));
$queueForStatsUsage
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$db->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
$response->noContent();
});
@ -2749,6 +2793,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'collections',
name: 'createIndex',
description: '/docs/references/databases/create-index.md',
auth: [AuthType::KEY],
@ -2919,6 +2964,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'indexes',
name: 'listIndexes',
description: '/docs/references/databases/list-indexes.md',
auth: [AuthType::KEY],
@ -2987,9 +3033,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT);
$indexes = $dbForProject->find('indexes', $queries);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'total' => $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT),
'indexes' => $dbForProject->find('indexes', $queries),
'total' => $total,
'indexes' => $indexes,
]), Response::MODEL_INDEX_LIST);
});
@ -3001,6 +3054,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'indexes',
name: 'getIndex',
description: '/docs/references/databases/get-index.md',
auth: [AuthType::KEY],
@ -3050,6 +3104,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk', new Method(
namespace: 'databases',
group: 'indexes',
name: 'deleteIndex',
description: '/docs/references/databases/delete-index.md',
auth: [AuthType::KEY],
@ -3128,6 +3183,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
[
new Method(
namespace: 'databases',
group: 'documents',
name: 'createDocument',
description: '/docs/references/databases/create-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -3356,8 +3412,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->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
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection
$response->addHeader('X-Debug-Operations', $operations);
@ -3390,6 +3445,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'listDocuments',
description: '/docs/references/databases/list-documents.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -3453,9 +3509,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$cursor->setValue($cursorDocument);
}
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT);
try {
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$operations = 0;
@ -3566,6 +3625,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'getDocument',
description: '/docs/references/databases/get-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -3677,6 +3737,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: 'logs',
name: 'listDocumentLogs',
description: '/docs/references/databases/get-document-logs.md',
auth: [AuthType::ADMIN],
@ -3797,6 +3858,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'updateDocument',
description: '/docs/references/databases/update-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -4051,6 +4113,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'deleteDocument',
description: '/docs/references/databases/delete-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -4141,8 +4204,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
$queueForStatsUsage
->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
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection
$response->addHeader('X-Debug-Operations', 1);
@ -4172,6 +4234,7 @@ App::get('/v1/databases/usage')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: null,
name: 'getUsage',
description: '/docs/references/databases/get-usage.md',
auth: [AuthType::ADMIN],
@ -4267,6 +4330,7 @@ App::get('/v1/databases/:databaseId/usage')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: null,
name: 'getDatabaseUsage',
description: '/docs/references/databases/get-database-usage.md',
auth: [AuthType::ADMIN],
@ -4368,6 +4432,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: 'databases',
group: null,
name: 'getCollectionUsage',
description: '/docs/references/databases/get-collection-usage.md',
auth: [AuthType::ADMIN],

View file

@ -44,6 +44,7 @@ App::get('/v1/graphql')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'get',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
hide: true,
@ -90,6 +91,7 @@ App::post('/v1/graphql/mutation')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'mutation',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
description: '/docs/references/graphql/post.md',
@ -140,6 +142,7 @@ App::post('/v1/graphql')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'query',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
description: '/docs/references/graphql/post.md',

View file

@ -32,6 +32,7 @@ App::get('/v1/health')
->label('scope', 'health.read')
->label('sdk', new Method(
namespace: 'health',
group: 'health',
name: 'get',
auth: [AuthType::KEY],
description: '/docs/references/health/get.md',
@ -71,6 +72,7 @@ App::get('/v1/health/db')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getDB',
description: '/docs/references/health/get-db.md',
responses: [
@ -131,6 +133,7 @@ App::get('/v1/health/cache')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getCache',
description: '/docs/references/health/get-cache.md',
responses: [
@ -195,6 +198,7 @@ App::get('/v1/health/pubsub')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getPubSub',
description: '/docs/references/health/get-pubsub.md',
responses: [
@ -259,6 +263,7 @@ App::get('/v1/health/time')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getTime',
description: '/docs/references/health/get-time.md',
responses: [
@ -322,6 +327,7 @@ App::get('/v1/health/queue/webhooks')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueWebhooks',
description: '/docs/references/health/get-queue-webhooks.md',
responses: [
@ -354,6 +360,7 @@ App::get('/v1/health/queue/logs')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueLogs',
description: '/docs/references/health/get-queue-logs.md',
responses: [
@ -386,6 +393,7 @@ App::get('/v1/health/certificate')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getCertificate',
description: '/docs/references/health/get-certificate.md',
responses: [
@ -442,6 +450,7 @@ App::get('/v1/health/queue/certificates')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueCertificates',
description: '/docs/references/health/get-queue-certificates.md',
responses: [
@ -474,6 +483,7 @@ App::get('/v1/health/queue/builds')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueBuilds',
description: '/docs/references/health/get-queue-builds.md',
responses: [
@ -506,6 +516,7 @@ App::get('/v1/health/queue/databases')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueDatabases',
description: '/docs/references/health/get-queue-databases.md',
responses: [
@ -539,6 +550,7 @@ App::get('/v1/health/queue/deletes')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueDeletes',
description: '/docs/references/health/get-queue-deletes.md',
responses: [
@ -571,6 +583,7 @@ App::get('/v1/health/queue/mails')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMails',
description: '/docs/references/health/get-queue-mails.md',
responses: [
@ -603,6 +616,7 @@ App::get('/v1/health/queue/messaging')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMessaging',
description: '/docs/references/health/get-queue-messaging.md',
responses: [
@ -635,6 +649,7 @@ App::get('/v1/health/queue/migrations')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMigrations',
description: '/docs/references/health/get-queue-migrations.md',
responses: [
@ -667,6 +682,7 @@ App::get('/v1/health/queue/functions')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueFunctions',
description: '/docs/references/health/get-queue-functions.md',
responses: [
@ -699,6 +715,7 @@ App::get('/v1/health/queue/stats-resources')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueStatsResources',
description: '/docs/references/health/get-queue-stats-resources.md',
responses: [
@ -731,6 +748,7 @@ App::get('/v1/health/queue/stats-usage')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueUsage',
description: '/docs/references/health/get-queue-stats-usage.md',
responses: [
@ -756,38 +774,6 @@ App::get('/v1/health/queue/stats-usage')
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
});
App::get('/v1/health/queue/stats-usage-dump')
->desc('Get usage dump queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
name: 'getQueueStatsUsageDump',
description: '/docs/references/health/get-queue-stats-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('publisher')
->inject('response')
->action(function (int|string $threshold, Publisher $publisher, Response $response) {
$threshold = \intval($threshold);
$size = $publisher->getQueueSize(new Queue(Event::STATS_USAGE_DUMP_QUEUE_NAME));
if ($size >= $threshold) {
throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}.");
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
});
App::get('/v1/health/storage/local')
->desc('Get local storage')
->groups(['api', 'health'])
@ -795,6 +781,7 @@ App::get('/v1/health/storage/local')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'storage',
name: 'getStorageLocal',
description: '/docs/references/health/get-storage-local.md',
responses: [
@ -844,6 +831,7 @@ App::get('/v1/health/storage')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'storage',
name: 'getStorage',
description: '/docs/references/health/get-storage.md',
responses: [
@ -892,6 +880,7 @@ App::get('/v1/health/anti-virus')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getAntivirus',
description: '/docs/references/health/get-storage-anti-virus.md',
responses: [
@ -937,6 +926,7 @@ App::get('/v1/health/queue/failed/:name')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getFailedJobs',
description: '/docs/references/health/get-failed-queue-jobs.md',
responses: [
@ -955,7 +945,6 @@ App::get('/v1/health/queue/failed/:name')
Event::FUNCTIONS_QUEUE_NAME,
Event::STATS_RESOURCES_QUEUE_NAME,
Event::STATS_USAGE_QUEUE_NAME,
Event::STATS_USAGE_DUMP_QUEUE_NAME,
Event::WEBHOOK_QUEUE_NAME,
Event::CERTIFICATES_QUEUE_NAME,
Event::BUILDS_QUEUE_NAME,
@ -981,9 +970,6 @@ App::get('/v1/health/stats') // Currently only used internally
->desc('Get system stats')
->groups(['api', 'health'])
->label('scope', 'root')
// ->label('sdk.auth', [APP_AUTH_TYPE_KEY])
// ->label('sdk.namespace', 'health')
// ->label('sdk.method', 'getStats')
->label('docs', false)
->inject('response')
->inject('register')

View file

@ -17,6 +17,7 @@ App::get('/v1/locale')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'get',
description: '/docs/references/locale/get-locale.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -80,6 +81,7 @@ App::get('/v1/locale/codes')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCodes',
description: '/docs/references/locale/list-locale-codes.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -105,6 +107,7 @@ App::get('/v1/locale/countries')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountries',
description: '/docs/references/locale/list-countries.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -141,6 +144,7 @@ App::get('/v1/locale/countries/eu')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountriesEU',
description: '/docs/references/locale/list-countries-eu.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -179,6 +183,7 @@ App::get('/v1/locale/countries/phones')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountriesPhones',
description: '/docs/references/locale/list-countries-phones.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -216,6 +221,7 @@ App::get('/v1/locale/continents')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listContinents',
description: '/docs/references/locale/list-continents.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -251,6 +257,7 @@ App::get('/v1/locale/currencies')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCurrencies',
description: '/docs/references/locale/list-currencies.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -277,6 +284,7 @@ App::get('/v1/locale/languages')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listLanguages',
description: '/docs/references/locale/list-languages.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],

View file

@ -30,6 +30,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
@ -63,6 +64,7 @@ App::post('/v1/messaging/providers/mailgun')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createMailgunProvider',
description: '/docs/references/messaging/create-mailgun-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -156,6 +158,7 @@ App::post('/v1/messaging/providers/sendgrid')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createSendgridProvider',
description: '/docs/references/messaging/create-sendgrid-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -237,6 +240,7 @@ App::post('/v1/messaging/providers/smtp')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createSmtpProvider',
description: '/docs/references/messaging/create-smtp-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -331,6 +335,7 @@ App::post('/v1/messaging/providers/msg91')
->label('event', 'providers.[providerId].create')
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createMsg91Provider',
description: '/docs/references/messaging/create-msg91-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -413,6 +418,7 @@ App::post('/v1/messaging/providers/telesign')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTelesignProvider',
description: '/docs/references/messaging/create-telesign-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -496,6 +502,7 @@ App::post('/v1/messaging/providers/textmagic')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTextmagicProvider',
description: '/docs/references/messaging/create-textmagic-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -579,6 +586,7 @@ App::post('/v1/messaging/providers/twilio')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTwilioProvider',
description: '/docs/references/messaging/create-twilio-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -662,6 +670,7 @@ App::post('/v1/messaging/providers/vonage')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createVonageProvider',
description: '/docs/references/messaging/create-vonage-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -745,6 +754,7 @@ App::post('/v1/messaging/providers/fcm')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createFcmProvider',
description: '/docs/references/messaging/create-fcm-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -814,6 +824,7 @@ App::post('/v1/messaging/providers/apns')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createApnsProvider',
description: '/docs/references/messaging/create-apns-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -903,6 +914,7 @@ App::get('/v1/messaging/providers')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'listProviders',
description: '/docs/references/messaging/list-providers.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -951,10 +963,15 @@ App::get('/v1/messaging/providers')
$cursor->setValue($cursorDocument);
}
try {
$providers = $dbForProject->find('providers', $queries);
$total = $dbForProject->count('providers', $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'providers' => $dbForProject->find('providers', $queries),
'total' => $dbForProject->count('providers', $queries, APP_LIMIT_COUNT),
'providers' => $providers,
'total' => $total,
]), Response::MODEL_PROVIDER_LIST);
});
@ -965,6 +982,7 @@ App::get('/v1/messaging/providers/:providerId/logs')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'listProviderLogs',
description: '/docs/references/messaging/list-provider-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1061,6 +1079,7 @@ App::get('/v1/messaging/providers/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'getProvider',
description: '/docs/references/messaging/get-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1094,6 +1113,7 @@ App::patch('/v1/messaging/providers/mailgun/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateMailgunProvider',
description: '/docs/references/messaging/update-mailgun-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1206,6 +1226,7 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateSendgridProvider',
description: '/docs/references/messaging/update-sendgrid-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1303,6 +1324,7 @@ App::patch('/v1/messaging/providers/smtp/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateSmtpProvider',
description: '/docs/references/messaging/update-smtp-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1431,6 +1453,7 @@ App::patch('/v1/messaging/providers/msg91/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateMsg91Provider',
description: '/docs/references/messaging/update-msg91-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1517,6 +1540,7 @@ App::patch('/v1/messaging/providers/telesign/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTelesignProvider',
description: '/docs/references/messaging/update-telesign-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1605,6 +1629,7 @@ App::patch('/v1/messaging/providers/textmagic/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTextmagicProvider',
description: '/docs/references/messaging/update-textmagic-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1693,6 +1718,7 @@ App::patch('/v1/messaging/providers/twilio/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTwilioProvider',
description: '/docs/references/messaging/update-twilio-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1781,6 +1807,7 @@ App::patch('/v1/messaging/providers/vonage/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateVonageProvider',
description: '/docs/references/messaging/update-vonage-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1869,6 +1896,7 @@ App::patch('/v1/messaging/providers/fcm/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateFcmProvider',
description: '/docs/references/messaging/update-fcm-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -1944,6 +1972,7 @@ App::patch('/v1/messaging/providers/apns/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateApnsProvider',
description: '/docs/references/messaging/update-apns-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2045,6 +2074,7 @@ App::delete('/v1/messaging/providers/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'deleteProvider',
description: '/docs/references/messaging/delete-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2087,6 +2117,7 @@ App::post('/v1/messaging/topics')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'createTopic',
description: '/docs/references/messaging/create-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2133,6 +2164,7 @@ App::get('/v1/messaging/topics')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'listTopics',
description: '/docs/references/messaging/list-topics.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2181,10 +2213,15 @@ App::get('/v1/messaging/topics')
$cursor->setValue($cursorDocument[0]);
}
try {
$topics = $dbForProject->find('topics', $queries);
$total = $dbForProject->count('topics', $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'topics' => $dbForProject->find('topics', $queries),
'total' => $dbForProject->count('topics', $queries, APP_LIMIT_COUNT),
'topics' => $topics,
'total' => $total,
]), Response::MODEL_TOPIC_LIST);
});
@ -2195,6 +2232,7 @@ App::get('/v1/messaging/topics/:topicId/logs')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'listTopicLogs',
description: '/docs/references/messaging/list-topic-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2292,6 +2330,7 @@ App::get('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'getTopic',
description: '/docs/references/messaging/get-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2326,6 +2365,7 @@ App::patch('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'updateTopic',
description: '/docs/references/messaging/update-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2376,6 +2416,7 @@ App::delete('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'deleteTopic',
description: '/docs/references/messaging/delete-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2423,6 +2464,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'createSubscriber',
description: '/docs/references/messaging/create-subscriber.md',
auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY],
@ -2522,6 +2564,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'listSubscribers',
description: '/docs/references/messaging/list-subscribers.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2579,8 +2622,11 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
$cursor->setValue($cursorDocument);
}
$subscribers = $dbForProject->find('subscribers', $queries);
try {
$subscribers = $dbForProject->find('subscribers', $queries);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) {
return function () use ($subscriber, $dbForProject) {
@ -2607,6 +2653,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'listSubscriberLogs',
description: '/docs/references/messaging/list-subscriber-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2704,6 +2751,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'getSubscriber',
description: '/docs/references/messaging/get-subscriber.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2752,6 +2800,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'deleteSubscriber',
description: '/docs/references/messaging/delete-subscriber.md',
auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY],
@ -2818,6 +2867,7 @@ App::post('/v1/messaging/messages/email')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createEmail',
description: '/docs/references/messaging/create-email.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -2976,6 +3026,7 @@ App::post('/v1/messaging/messages/sms')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createSms',
description: '/docs/references/messaging/create-sms.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3098,6 +3149,7 @@ App::post('/v1/messaging/messages/push')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createPush',
description: '/docs/references/messaging/create-push.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3312,6 +3364,7 @@ App::get('/v1/messaging/messages')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'listMessages',
description: '/docs/references/messaging/list-messages.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3360,10 +3413,15 @@ App::get('/v1/messaging/messages')
$cursor->setValue($cursorDocument);
}
try {
$messages = $dbForProject->find('messages', $queries);
$total = $dbForProject->count('messages', $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'messages' => $dbForProject->find('messages', $queries),
'total' => $dbForProject->count('messages', $queries, APP_LIMIT_COUNT),
'messages' => $messages,
'total' => $total,
]), Response::MODEL_MESSAGE_LIST);
});
@ -3374,6 +3432,7 @@ App::get('/v1/messaging/messages/:messageId/logs')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'logs',
name: 'listMessageLogs',
description: '/docs/references/messaging/list-message-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3471,6 +3530,7 @@ App::get('/v1/messaging/messages/:messageId/targets')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'listTargets',
description: '/docs/references/messaging/list-message-targets.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3533,10 +3593,15 @@ App::get('/v1/messaging/messages/:messageId/targets')
$cursor->setValue($cursorDocument);
}
try {
$targets = $dbForProject->find('targets', $queries);
$total = $dbForProject->count('targets', $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'targets' => $dbForProject->find('targets', $queries),
'total' => $dbForProject->count('targets', $queries, APP_LIMIT_COUNT),
'targets' => $targets,
'total' => $total,
]), Response::MODEL_TARGET_LIST);
});
@ -3547,6 +3612,7 @@ App::get('/v1/messaging/messages/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'getMessage',
description: '/docs/references/messaging/get-message.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3580,6 +3646,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updateEmail',
description: '/docs/references/messaging/update-email.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3786,6 +3853,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updateSms',
description: '/docs/references/messaging/update-sms.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -3947,6 +4015,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updatePush',
description: '/docs/references/messaging/update-push.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@ -4206,6 +4275,7 @@ App::delete('/v1/messaging/messages/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'delete',
description: '/docs/references/messaging/delete-message.md',
auth: [AuthType::ADMIN, AuthType::KEY],

View file

@ -15,6 +15,7 @@ use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
@ -43,12 +44,13 @@ include_once __DIR__ . '/../shared/api.php';
App::post('/v1/migrations/appwrite')
->groups(['api', 'migrations'])
->desc('Migrate Appwrite data')
->desc('Create Appwrite migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createAppwriteMigration',
description: '/docs/references/migrations/migration-appwrite.md',
auth: [AuthType::ADMIN],
@ -103,12 +105,13 @@ App::post('/v1/migrations/appwrite')
App::post('/v1/migrations/firebase')
->groups(['api', 'migrations'])
->desc('Migrate Firebase data')
->desc('Create Firebase migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createFirebaseMigration',
description: '/docs/references/migrations/migration-firebase.md',
auth: [AuthType::ADMIN],
@ -169,12 +172,13 @@ App::post('/v1/migrations/firebase')
App::post('/v1/migrations/supabase')
->groups(['api', 'migrations'])
->desc('Migrate Supabase data')
->desc('Create Supabase migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createSupabaseMigration',
description: '/docs/references/migrations/migration-supabase.md',
auth: [AuthType::ADMIN],
@ -235,12 +239,13 @@ App::post('/v1/migrations/supabase')
App::post('/v1/migrations/nhost')
->groups(['api', 'migrations'])
->desc('Migrate NHost data')
->desc('Create NHost migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createNHostMigration',
description: '/docs/references/migrations/migration-nhost.md',
auth: [AuthType::ADMIN],
@ -309,6 +314,7 @@ App::post('/v1/migrations/csv')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createCsvMigration',
description: '/docs/references/migrations/migration-csv.md',
auth: [AuthType::ADMIN],
@ -431,6 +437,7 @@ App::get('/v1/migrations')
->label('scope', 'migrations.read')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'list',
description: '/docs/references/migrations/list-migrations.md',
auth: [AuthType::ADMIN],
@ -482,10 +489,15 @@ App::get('/v1/migrations')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$migrations = $dbForProject->find('migrations', $queries);
$total = $dbForProject->count('migrations', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'migrations' => $dbForProject->find('migrations', $queries),
'total' => $dbForProject->count('migrations', $filterQueries, APP_LIMIT_COUNT),
'migrations' => $migrations,
'total' => $total,
]), Response::MODEL_MIGRATION_LIST);
});
@ -495,6 +507,7 @@ App::get('/v1/migrations/:migrationId')
->label('scope', 'migrations.read')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'get',
description: '/docs/references/migrations/get-migration.md',
auth: [AuthType::ADMIN],
@ -520,10 +533,11 @@ App::get('/v1/migrations/:migrationId')
App::get('/v1/migrations/appwrite/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Appwrite data')
->desc('Get Appwrite migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getAppwriteReport',
description: '/docs/references/migrations/migration-appwrite-report.md',
auth: [AuthType::ADMIN],
@ -543,6 +557,7 @@ App::get('/v1/migrations/appwrite/report')
->inject('project')
->inject('user')
->action(function (array $resources, string $endpoint, string $projectID, string $key, Response $response) {
$appwrite = new Appwrite($projectID, $endpoint, $key);
try {
@ -567,10 +582,11 @@ App::get('/v1/migrations/appwrite/report')
App::get('/v1/migrations/firebase/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Firebase data')
->desc('Get Firebase migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getFirebaseReport',
description: '/docs/references/migrations/migration-firebase-report.md',
auth: [AuthType::ADMIN],
@ -619,10 +635,11 @@ App::get('/v1/migrations/firebase/report')
App::get('/v1/migrations/supabase/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Supabase Data')
->desc('Get Supabase migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getSupabaseReport',
description: '/docs/references/migrations/migration-supabase-report.md',
auth: [AuthType::ADMIN],
@ -667,10 +684,11 @@ App::get('/v1/migrations/supabase/report')
App::get('/v1/migrations/nhost/report')
->groups(['api', 'migrations'])
->desc('Generate a report on NHost Data')
->desc('Get NHost migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getNHostReport',
description: '/docs/references/migrations/migration-nhost-report.md',
auth: [AuthType::ADMIN],
@ -715,13 +733,14 @@ App::get('/v1/migrations/nhost/report')
App::patch('/v1/migrations/:migrationId')
->groups(['api', 'migrations'])
->desc('Retry migration')
->desc('Update retry migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].retry')
->label('audits.event', 'migration.retry')
->label('audits.resource', 'migrations/{request.migrationId}')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'retry',
description: '/docs/references/migrations/retry-migration.md',
auth: [AuthType::ADMIN],
@ -772,6 +791,7 @@ App::delete('/v1/migrations/:migrationId')
->label('audits.resource', 'migrations/{request.migrationId}')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'delete',
description: '/docs/references/migrations/delete-migration.md',
auth: [AuthType::ADMIN],

View file

@ -27,6 +27,7 @@ App::get('/v1/project/usage')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'getUsage',
description: '/docs/references/project/get-usage.md',
auth: [AuthType::ADMIN],
@ -388,6 +389,7 @@ App::post('/v1/project/variables')
->label('audits.event', 'variable.create')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'createVariable',
description: '/docs/references/project/create-variable.md',
auth: [AuthType::ADMIN],
@ -449,6 +451,7 @@ App::get('/v1/project/variables')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'listVariables',
description: '/docs/references/project/list-variables.md',
auth: [AuthType::ADMIN],
@ -479,6 +482,7 @@ App::get('/v1/project/variables/:variableId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'getVariable',
description: '/docs/references/project/get-variable.md',
auth: [AuthType::ADMIN],
@ -508,6 +512,7 @@ App::put('/v1/project/variables/:variableId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'updateVariable',
description: '/docs/references/project/update-variable.md',
auth: [AuthType::ADMIN],
@ -565,6 +570,7 @@ App::delete('/v1/project/variables/:variableId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'deleteVariable',
description: '/docs/references/project/delete-variable.md',
auth: [AuthType::ADMIN],

View file

@ -28,6 +28,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -68,6 +69,7 @@ App::post('/v1/projects')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'create',
description: '/docs/references/projects/create.md',
auth: [AuthType::ADMIN],
@ -138,6 +140,14 @@ App::post('/v1/projects')
$databases = Config::getParam('pools-database', []);
if ($region !== 'default') {
$databaseKeys = System::getEnv('_APP_DATABASE_KEYS', '');
$keys = explode(',', $databaseKeys);
$databases = array_filter($keys, function ($value) use ($region) {
return str_contains($value, $region);
});
}
$databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE');
$index = \array_search($databaseOverride, $databases);
if ($index !== false) {
@ -205,17 +215,17 @@ App::post('/v1/projects')
$dsn = new DSN('mysql://' . $dsn);
}
$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', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
$sharedTables = $sharedTablesV1 || $sharedTablesV2;
if (!$sharedTablesV2) {
$adapter = $pools->get($dsn->getHost())->pop()->getResource();
$dbForProject = new Database($adapter, $cache);
if ($sharedTables) {
$dbForProject
->setSharedTables(true)
@ -297,6 +307,7 @@ App::get('/v1/projects')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'list',
description: '/docs/references/projects/list.md',
auth: [AuthType::ADMIN],
@ -349,10 +360,15 @@ App::get('/v1/projects')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$projects = $dbForPlatform->find('projects', $queries);
$total = $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'projects' => $dbForPlatform->find('projects', $queries),
'total' => $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT),
'projects' => $projects,
'total' => $total,
]), Response::MODEL_PROJECT_LIST);
});
@ -362,6 +378,7 @@ App::get('/v1/projects/:projectId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'get',
description: '/docs/references/projects/get.md',
auth: [AuthType::ADMIN],
@ -394,6 +411,7 @@ App::patch('/v1/projects/:projectId')
->label('audits.resource', 'project/{request.projectId}')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'update',
description: '/docs/references/projects/update.md',
auth: [AuthType::ADMIN],
@ -447,6 +465,7 @@ App::patch('/v1/projects/:projectId/team')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateTeam',
description: '/docs/references/projects/update-team.md',
auth: [AuthType::ADMIN],
@ -521,6 +540,7 @@ App::patch('/v1/projects/:projectId/service')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateServiceStatus',
description: '/docs/references/projects/update-service-status.md',
auth: [AuthType::ADMIN],
@ -558,6 +578,7 @@ App::patch('/v1/projects/:projectId/service/all')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateServiceStatusAll',
description: '/docs/references/projects/update-service-status-all.md',
auth: [AuthType::ADMIN],
@ -598,6 +619,7 @@ App::patch('/v1/projects/:projectId/api')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateApiStatus',
description: '/docs/references/projects/update-api-status.md',
auth: [AuthType::ADMIN],
@ -635,6 +657,7 @@ App::patch('/v1/projects/:projectId/api/all')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateApiStatusAll',
description: '/docs/references/projects/update-api-status-all.md',
auth: [AuthType::ADMIN],
@ -675,6 +698,7 @@ App::patch('/v1/projects/:projectId/oauth2')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateOAuth2',
description: '/docs/references/projects/update-oauth2.md',
auth: [AuthType::ADMIN],
@ -725,6 +749,7 @@ App::patch('/v1/projects/:projectId/auth/session-alerts')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateSessionAlerts',
description: '/docs/references/projects/update-session-alerts.md',
auth: [AuthType::ADMIN],
@ -762,6 +787,7 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateMembershipsPrivacy',
description: '/docs/references/projects/update-memberships-privacy.md',
auth: [AuthType::ADMIN],
@ -803,6 +829,7 @@ App::patch('/v1/projects/:projectId/auth/limit')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthLimit',
description: '/docs/references/projects/update-auth-limit.md',
auth: [AuthType::ADMIN],
@ -840,6 +867,7 @@ App::patch('/v1/projects/:projectId/auth/duration')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthDuration',
description: '/docs/references/projects/update-auth-duration.md',
auth: [AuthType::ADMIN],
@ -877,6 +905,7 @@ App::patch('/v1/projects/:projectId/auth/:method')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthStatus',
description: '/docs/references/projects/update-auth-status.md',
auth: [AuthType::ADMIN],
@ -917,6 +946,7 @@ App::patch('/v1/projects/:projectId/auth/password-history')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthPasswordHistory',
description: '/docs/references/projects/update-auth-password-history.md',
auth: [AuthType::ADMIN],
@ -954,6 +984,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthPasswordDictionary',
description: '/docs/references/projects/update-auth-password-dictionary.md',
auth: [AuthType::ADMIN],
@ -986,11 +1017,12 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary')
});
App::patch('/v1/projects/:projectId/auth/personal-data')
->desc('Enable or disable checking user passwords for similarity with their personal data.')
->desc('Update personal data check')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updatePersonalDataCheck',
description: '/docs/references/projects/update-personal-data-check.md',
auth: [AuthType::ADMIN],
@ -1028,6 +1060,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthSessionsLimit',
description: '/docs/references/projects/update-auth-sessions-limit.md',
auth: [AuthType::ADMIN],
@ -1065,6 +1098,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateMockNumbers',
description: '/docs/references/projects/update-mock-numbers.md',
auth: [AuthType::ADMIN],
@ -1112,6 +1146,7 @@ App::delete('/v1/projects/:projectId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'delete',
description: '/docs/references/projects/delete.md',
auth: [AuthType::ADMIN],
@ -1155,6 +1190,7 @@ App::post('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'createWebhook',
description: '/docs/references/projects/create-webhook.md',
auth: [AuthType::ADMIN],
@ -1219,6 +1255,7 @@ App::get('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'listWebhooks',
description: '/docs/references/projects/list-webhooks.md',
auth: [AuthType::ADMIN],
@ -1257,6 +1294,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'getWebhook',
description: '/docs/references/projects/get-webhook.md',
auth: [AuthType::ADMIN],
@ -1297,6 +1335,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'updateWebhook',
description: '/docs/references/projects/update-webhook.md',
auth: [AuthType::ADMIN],
@ -1362,6 +1401,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'updateWebhookSignature',
description: '/docs/references/projects/update-webhook-signature.md',
auth: [AuthType::ADMIN],
@ -1407,6 +1447,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'deleteWebhook',
description: '/docs/references/projects/delete-webhook.md',
auth: [AuthType::ADMIN],
@ -1454,6 +1495,7 @@ App::post('/v1/projects/:projectId/keys')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'createKey',
description: '/docs/references/projects/create-key.md',
auth: [AuthType::ADMIN],
@ -1510,6 +1552,7 @@ App::get('/v1/projects/:projectId/keys')
->label('scope', 'keys.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'listKeys',
description: '/docs/references/projects/list-keys.md',
auth: [AuthType::ADMIN],
@ -1548,6 +1591,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'getKey',
description: '/docs/references/projects/get-key.md',
auth: [AuthType::ADMIN],
@ -1588,6 +1632,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'updateKey',
description: '/docs/references/projects/update-key.md',
auth: [AuthType::ADMIN],
@ -1640,6 +1685,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'deleteKey',
description: '/docs/references/projects/delete-key.md',
auth: [AuthType::ADMIN],
@ -1687,6 +1733,7 @@ App::post('/v1/projects/:projectId/jwts')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'createJWT',
description: '/docs/references/projects/create-jwt.md',
auth: [AuthType::ADMIN],
@ -1730,6 +1777,7 @@ App::post('/v1/projects/:projectId/platforms')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'createPlatform',
description: '/docs/references/projects/create-platform.md',
auth: [AuthType::ADMIN],
@ -1786,6 +1834,7 @@ App::get('/v1/projects/:projectId/platforms')
->label('scope', 'platforms.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'listPlatforms',
description: '/docs/references/projects/list-platforms.md',
auth: [AuthType::ADMIN],
@ -1824,6 +1873,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'getPlatform',
description: '/docs/references/projects/get-platform.md',
auth: [AuthType::ADMIN],
@ -1864,6 +1914,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'updatePlatform',
description: '/docs/references/projects/update-platform.md',
auth: [AuthType::ADMIN],
@ -1919,6 +1970,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'deletePlatform',
description: '/docs/references/projects/delete-platform.md',
auth: [AuthType::ADMIN],
@ -1966,6 +2018,7 @@ App::patch('/v1/projects/:projectId/smtp')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateSmtp',
description: '/docs/references/projects/update-smtp.md',
auth: [AuthType::ADMIN],
@ -2062,6 +2115,7 @@ App::post('/v1/projects/:projectId/smtp/tests')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'createSmtpTest',
description: '/docs/references/projects/create-smtp-test.md',
auth: [AuthType::ADMIN],
@ -2128,6 +2182,7 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'getSmsTemplate',
description: '/docs/references/projects/get-sms-template.md',
auth: [AuthType::ADMIN],
@ -2175,6 +2230,7 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'getEmailTemplate',
description: '/docs/references/projects/get-email-template.md',
auth: [AuthType::ADMIN],
@ -2233,6 +2289,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateSmsTemplate',
description: '/docs/references/projects/update-sms-template.md',
auth: [AuthType::ADMIN],
@ -2279,6 +2336,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateEmailTemplate',
description: '/docs/references/projects/update-email-template.md',
auth: [AuthType::ADMIN],
@ -2335,6 +2393,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'deleteSmsTemplate',
description: '/docs/references/projects/delete-sms-template.md',
auth: [AuthType::ADMIN],
@ -2380,11 +2439,12 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
});
App::delete('/v1/projects/:projectId/templates/email/:type/:locale')
->desc('Reset custom email template')
->desc('Delete custom email template')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'deleteEmailTemplate',
description: '/docs/references/projects/delete-email-template.md',
auth: [AuthType::ADMIN],

View file

@ -31,6 +31,7 @@ App::get('/v1/proxy/rules')
->label('scope', 'rules.read')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'listRules',
description: '/docs/references/proxy/list-rules.md',
auth: [AuthType::ADMIN],
@ -105,6 +106,7 @@ App::get('/v1/proxy/rules/:ruleId')
->label('scope', 'rules.read')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'getRule',
description: '/docs/references/proxy/get-rule.md',
auth: [AuthType::ADMIN],
@ -142,6 +144,7 @@ App::delete('/v1/proxy/rules/:ruleId')
->label('audits.resource', 'rule/{request.ruleId}')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'deleteRule',
description: '/docs/references/proxy/delete-rule.md',
auth: [AuthType::ADMIN],
@ -186,6 +189,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
->label('audits.resource', 'rule/{response.$id}')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'updateRuleVerification',
description: '/docs/references/proxy/update-rule-verification.md',
auth: [AuthType::ADMIN],

View file

@ -24,6 +24,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -62,6 +63,7 @@ App::post('/v1/storage/buckets')
->label('audits.resource', 'bucket/{response.$id}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'createBucket',
description: '/docs/references/storage/create-bucket.md',
auth: [AuthType::KEY],
@ -164,6 +166,7 @@ App::get('/v1/storage/buckets')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'listBuckets',
description: '/docs/references/storage/list-buckets.md',
auth: [AuthType::KEY],
@ -216,10 +219,15 @@ App::get('/v1/storage/buckets')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$buckets = $dbForProject->find('buckets', $queries);
$total = $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'buckets' => $dbForProject->find('buckets', $queries),
'total' => $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT),
'buckets' => $buckets,
'total' => $total,
]), Response::MODEL_BUCKET_LIST);
});
@ -230,6 +238,7 @@ App::get('/v1/storage/buckets/:bucketId')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'getBucket',
description: '/docs/references/storage/get-bucket.md',
auth: [AuthType::KEY],
@ -264,6 +273,7 @@ App::put('/v1/storage/buckets/:bucketId')
->label('audits.resource', 'bucket/{response.$id}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'updateBucket',
description: '/docs/references/storage/update-bucket.md',
auth: [AuthType::KEY],
@ -334,6 +344,7 @@ App::delete('/v1/storage/buckets/:bucketId')
->label('audits.resource', 'bucket/{request.bucketId}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'deleteBucket',
description: '/docs/references/storage/delete-bucket.md',
auth: [AuthType::KEY],
@ -387,6 +398,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'createFile',
description: '/docs/references/storage/create-file.md',
type: MethodType::UPLOAD,
@ -756,6 +768,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'listFiles',
description: '/docs/references/storage/list-files.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -837,6 +850,8 @@ App::get('/v1/storage/buckets/:bucketId/files')
}
} catch (NotFoundException) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
@ -853,6 +868,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFile',
description: '/docs/references/storage/get-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -909,6 +925,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->label('cache.resource', 'file/{request.fileId}')
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFilePreview',
description: '/docs/references/storage/get-file-preview.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1097,6 +1114,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFileDownload',
description: '/docs/references/storage/get-file-download.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1245,6 +1263,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFileView',
description: '/docs/references/storage/get-file-view.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1408,9 +1427,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
->groups(['api', 'storage'])
->label('scope', 'public')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', '*/*')
->label('sdk.methodType', 'location')
->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('jwt', '', new Text(2048, 0), 'JSON Web Token to validate', true)
@ -1571,6 +1587,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'updateFile',
description: '/docs/references/storage/update-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1685,6 +1702,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'deleteFile',
description: '/docs/references/storage/delete-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1785,6 +1803,7 @@ App::get('/v1/storage/usage')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: null,
name: 'getUsage',
description: '/docs/references/storage/get-usage.md',
auth: [AuthType::ADMIN],
@ -1871,6 +1890,7 @@ App::get('/v1/storage/:bucketId/usage')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: null,
name: 'getBucketUsage',
description: '/docs/references/storage/get-bucket-usage.md',
auth: [AuthType::ADMIN],

View file

@ -33,6 +33,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -63,6 +64,7 @@ App::post('/v1/teams')
->label('audits.resource', 'team/{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'create',
description: '/docs/references/teams/create-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -153,6 +155,7 @@ App::get('/v1/teams')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'list',
description: '/docs/references/teams/list-teams.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -205,9 +208,12 @@ App::get('/v1/teams')
}
$filterQueries = Query::groupByType($queries)['filters'];
$results = $dbForProject->find('teams', $queries);
$total = $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT);
try {
$results = $dbForProject->find('teams', $queries);
$total = $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'teams' => $results,
@ -221,6 +227,7 @@ App::get('/v1/teams/:teamId')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'get',
description: '/docs/references/teams/get-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -251,6 +258,7 @@ App::get('/v1/teams/:teamId/prefs')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'getPrefs',
description: '/docs/references/teams/get-team-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -286,6 +294,7 @@ App::put('/v1/teams/:teamId')
->label('audits.resource', 'team/{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'updateName',
description: '/docs/references/teams/update-team-name.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -333,6 +342,7 @@ App::put('/v1/teams/:teamId/prefs')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'updatePrefs',
description: '/docs/references/teams/update-team-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -372,6 +382,7 @@ App::delete('/v1/teams/:teamId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'delete',
description: '/docs/references/teams/delete-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -430,6 +441,7 @@ App::post('/v1/teams/:teamId/memberships')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'createMembership',
description: '/docs/references/teams/create-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -797,6 +809,7 @@ App::get('/v1/teams/:teamId/memberships')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'listMemberships',
description: '/docs/references/teams/list-team-members.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -860,17 +873,20 @@ App::get('/v1/teams/:teamId/memberships')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$memberships = $dbForProject->find(
collection: 'memberships',
queries: $queries,
);
$total = $dbForProject->count(
collection: 'memberships',
queries: $filterQueries,
max: APP_LIMIT_COUNT
);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$memberships = $dbForProject->find(
collection: 'memberships',
queries: $queries,
);
$total = $dbForProject->count(
collection: 'memberships',
queries: $filterQueries,
max: APP_LIMIT_COUNT
);
$memberships = array_filter($memberships, fn (Document $membership) => !empty($membership->getAttribute('userId')));
@ -935,6 +951,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'getMembership',
description: '/docs/references/teams/get-team-member.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1021,6 +1038,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'updateMembership',
description: '/docs/references/teams/update-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1124,6 +1142,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'updateMembershipStatus',
description: '/docs/references/teams/update-team-membership-status.md',
auth: [AuthType::SESSION, AuthType::JWT],
@ -1281,6 +1300,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'deleteMembership',
description: '/docs/references/teams/delete-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@ -1351,6 +1371,7 @@ App::get('/v1/teams/:teamId/logs')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'logs',
name: 'listLogs',
description: '/docs/references/teams/get-team-logs.md',
auth: [AuthType::ADMIN],

View file

@ -34,6 +34,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -192,6 +193,7 @@ App::post('/v1/users')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'create',
description: '/docs/references/users/create-user.md',
auth: [AuthType::KEY],
@ -226,6 +228,7 @@ App::post('/v1/users/bcrypt')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createBcryptUser',
description: '/docs/references/users/create-bcrypt-user.md',
auth: [AuthType::KEY],
@ -260,6 +263,7 @@ App::post('/v1/users/md5')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createMD5User',
description: '/docs/references/users/create-md5-user.md',
auth: [AuthType::KEY],
@ -294,6 +298,7 @@ App::post('/v1/users/argon2')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createArgon2User',
description: '/docs/references/users/create-argon2-user.md',
auth: [AuthType::KEY],
@ -328,6 +333,7 @@ App::post('/v1/users/sha')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createSHAUser',
description: '/docs/references/users/create-sha-user.md',
auth: [AuthType::KEY],
@ -369,6 +375,7 @@ App::post('/v1/users/phpass')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createPHPassUser',
description: '/docs/references/users/create-phpass-user.md',
auth: [AuthType::KEY],
@ -403,6 +410,7 @@ App::post('/v1/users/scrypt')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createScryptUser',
description: '/docs/references/users/create-scrypt-user.md',
auth: [AuthType::KEY],
@ -450,6 +458,7 @@ App::post('/v1/users/scrypt-modified')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createScryptModifiedUser',
description: '/docs/references/users/create-scrypt-modified-user.md',
auth: [AuthType::KEY],
@ -488,6 +497,7 @@ App::post('/v1/users/:userId/targets')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'createTarget',
description: '/docs/references/users/create-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@ -579,6 +589,7 @@ App::get('/v1/users')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'list',
description: '/docs/references/users/list-users.md',
auth: [AuthType::KEY],
@ -631,10 +642,15 @@ App::get('/v1/users')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$users = $dbForProject->find('users', $queries);
$total = $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'users' => $dbForProject->find('users', $queries),
'total' => $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT),
'users' => $users,
'total' => $total,
]), Response::MODEL_USER_LIST);
});
@ -644,6 +660,7 @@ App::get('/v1/users/:userId')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'get',
description: '/docs/references/users/get-user.md',
auth: [AuthType::KEY],
@ -674,6 +691,7 @@ App::get('/v1/users/:userId/prefs')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'getPrefs',
description: '/docs/references/users/get-user-prefs.md',
auth: [AuthType::KEY],
@ -706,6 +724,7 @@ App::get('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.read')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'getTarget',
description: '/docs/references/users/get-user-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@ -743,6 +762,7 @@ App::get('/v1/users/:userId/sessions')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'listSessions',
description: '/docs/references/users/list-user-sessions.md',
auth: [AuthType::KEY],
@ -789,6 +809,7 @@ App::get('/v1/users/:userId/memberships')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'memberships',
name: 'listMemberships',
description: '/docs/references/users/list-user-memberships.md',
auth: [AuthType::KEY],
@ -848,6 +869,7 @@ App::get('/v1/users/:userId/logs')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'logs',
name: 'listLogs',
description: '/docs/references/users/list-user-logs.md',
auth: [AuthType::KEY],
@ -944,6 +966,7 @@ App::get('/v1/users/:userId/targets')
->label('scope', 'targets.read')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'listTargets',
description: '/docs/references/users/list-user-targets.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@ -996,10 +1019,15 @@ App::get('/v1/users/:userId/targets')
$cursor->setValue($cursorDocument);
}
try {
$targets = $dbForProject->find('targets', $queries);
$total = $dbForProject->count('targets', $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'targets' => $dbForProject->find('targets', $queries),
'total' => $dbForProject->count('targets', $queries, APP_LIMIT_COUNT),
'targets' => $targets,
'total' => $total,
]), Response::MODEL_TARGET_LIST);
});
@ -1009,6 +1037,7 @@ App::get('/v1/users/identities')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'identities',
name: 'listIdentities',
description: '/docs/references/users/list-identities.md',
auth: [AuthType::KEY],
@ -1061,10 +1090,15 @@ App::get('/v1/users/identities')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$identities = $dbForProject->find('identities', $queries);
$total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'identities' => $dbForProject->find('identities', $queries),
'total' => $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT),
'identities' => $identities,
'total' => $total,
]), Response::MODEL_IDENTITY_LIST);
});
@ -1078,6 +1112,7 @@ App::patch('/v1/users/:userId/status')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateStatus',
description: '/docs/references/users/update-user-status.md',
auth: [AuthType::KEY],
@ -1118,6 +1153,7 @@ App::put('/v1/users/:userId/labels')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateLabels',
description: '/docs/references/users/update-user-labels.md',
auth: [AuthType::KEY],
@ -1160,6 +1196,7 @@ App::patch('/v1/users/:userId/verification/phone')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePhoneVerification',
description: '/docs/references/users/update-user-phone-verification.md',
auth: [AuthType::KEY],
@ -1201,6 +1238,7 @@ App::patch('/v1/users/:userId/name')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateName',
description: '/docs/references/users/update-user-name.md',
auth: [AuthType::KEY],
@ -1243,6 +1281,7 @@ App::patch('/v1/users/:userId/password')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePassword',
description: '/docs/references/users/update-user-password.md',
auth: [AuthType::KEY],
@ -1325,6 +1364,7 @@ App::patch('/v1/users/:userId/email')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateEmail',
description: '/docs/references/users/update-user-email.md',
auth: [AuthType::KEY],
@ -1424,6 +1464,7 @@ App::patch('/v1/users/:userId/phone')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePhone',
description: '/docs/references/users/update-user-phone.md',
auth: [AuthType::KEY],
@ -1513,6 +1554,7 @@ App::patch('/v1/users/:userId/verification')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateEmailVerification',
description: '/docs/references/users/update-user-email-verification.md',
auth: [AuthType::KEY],
@ -1550,6 +1592,7 @@ App::patch('/v1/users/:userId/prefs')
->label('scope', 'users.write')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePrefs',
description: '/docs/references/users/update-user-prefs.md',
auth: [AuthType::KEY],
@ -1590,6 +1633,7 @@ App::patch('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'updateTarget',
description: '/docs/references/users/update-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@ -1694,6 +1738,7 @@ App::patch('/v1/users/:userId/mfa')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateMfa',
description: '/docs/references/users/update-user-mfa.md',
auth: [AuthType::KEY],
@ -1733,6 +1778,7 @@ App::get('/v1/users/:userId/mfa/factors')
->label('usage.metric', 'users.{scope}.requests.read')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'listMfaFactors',
description: '/docs/references/users/list-mfa-factors.md',
auth: [AuthType::KEY],
@ -1771,6 +1817,7 @@ App::get('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.read')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'getMfaRecoveryCodes',
description: '/docs/references/users/get-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@ -1815,6 +1862,7 @@ App::patch('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'createMfaRecoveryCodes',
description: '/docs/references/users/create-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@ -1856,7 +1904,7 @@ App::patch('/v1/users/:userId/mfa/recovery-codes')
});
App::put('/v1/users/:userId/mfa/recovery-codes')
->desc('Regenerate MFA recovery codes')
->desc('Update MFA recovery codes (regenerate)')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.mfa.recovery-codes')
->label('scope', 'users.write')
@ -1866,6 +1914,7 @@ App::put('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'updateMfaRecoveryCodes',
description: '/docs/references/users/update-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@ -1916,6 +1965,7 @@ App::delete('/v1/users/:userId/mfa/authenticators/:type')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'deleteMfaAuthenticator',
description: '/docs/references/users/delete-mfa-authenticator.md',
auth: [AuthType::KEY],
@ -1963,6 +2013,7 @@ App::post('/v1/users/:userId/sessions')
->label('usage.metric', 'sessions.{scope}.requests.create')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createSession',
description: '/docs/references/users/create-session.md',
auth: [AuthType::KEY],
@ -2047,6 +2098,7 @@ App::post('/v1/users/:userId/tokens')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createToken',
description: '/docs/references/users/create-token.md',
auth: [AuthType::KEY],
@ -2109,6 +2161,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'deleteSession',
description: '/docs/references/users/delete-user-session.md',
auth: [AuthType::KEY],
@ -2159,6 +2212,7 @@ App::delete('/v1/users/:userId/sessions')
->label('audits.resource', 'user/{user.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'deleteSessions',
description: '/docs/references/users/delete-user-sessions.md',
auth: [AuthType::KEY],
@ -2208,6 +2262,7 @@ App::delete('/v1/users/:userId')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'delete',
description: '/docs/references/users/delete.md',
auth: [AuthType::KEY],
@ -2257,6 +2312,7 @@ App::delete('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'deleteTarget',
description: '/docs/references/users/delete-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@ -2314,6 +2370,7 @@ App::delete('/v1/users/identities/:identityId')
->label('audits.resource', 'identity/{request.$identityId}')
->label('sdk', new Method(
namespace: 'users',
group: 'identities',
name: 'deleteIdentity',
description: '/docs/references/users/delete-identity.md',
auth: [AuthType::KEY],
@ -2353,6 +2410,7 @@ App::post('/v1/users/:userId/jwts')
->label('scope', 'users.write')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createJWT',
description: '/docs/references/users/create-user-jwt.md',
auth: [AuthType::KEY],
@ -2408,6 +2466,7 @@ App::get('/v1/users/usage')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: null,
name: 'getUsage',
description: '/docs/references/users/get-usage.md',
auth: [AuthType::ADMIN],

View file

@ -19,6 +19,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -397,12 +398,13 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
};
App::get('/v1/vcs/github/authorize')
->desc('Install GitHub app')
->desc('Create GitHub app installation')
->groups(['api', 'vcs'])
->label('scope', 'vcs.read')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'createGitHubInstallation',
description: '/docs/references/vcs/create-github-installation.md',
auth: [AuthType::ADMIN],
@ -446,7 +448,7 @@ App::get('/v1/vcs/github/authorize')
});
App::get('/v1/vcs/github/callback')
->desc('Capture installation and authorization from GitHub app')
->desc('Get installation and authorization from GitHub app')
->groups(['api', 'vcs'])
->label('scope', 'public')
->label('error', __DIR__ . '/../../views/general/error.phtml')
@ -584,6 +586,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'getRepositoryContents',
description: '/docs/references/vcs/get-repository-contents.md',
auth: [AuthType::ADMIN],
@ -651,6 +654,7 @@ App::post('/v1/vcs/github/installations/:installationId/detections')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'createRepositoryDetection',
description: '/docs/references/vcs/create-repository-detection.md',
auth: [AuthType::ADMIN],
@ -808,6 +812,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'listRepositories',
description: '/docs/references/vcs/list-repositories.md',
auth: [AuthType::ADMIN],
@ -959,6 +964,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'createRepository',
description: '/docs/references/vcs/create-repository.md',
auth: [AuthType::ADMIN],
@ -1071,6 +1077,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'getRepository',
description: '/docs/references/vcs/get-repository.md',
auth: [AuthType::ADMIN],
@ -1125,6 +1132,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'listRepositoryBranches',
description: '/docs/references/vcs/list-repository-branches.md',
auth: [AuthType::ADMIN],
@ -1318,6 +1326,7 @@ App::get('/v1/vcs/installations')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'listInstallations',
description: '/docs/references/vcs/list-installations.md',
auth: [AuthType::ADMIN],
@ -1373,9 +1382,12 @@ App::get('/v1/vcs/installations')
}
$filterQueries = Query::groupByType($queries)['filters'];
$results = $dbForPlatform->find('installations', $queries);
$total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT);
try {
$results = $dbForPlatform->find('installations', $queries);
$total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
$response->dynamic(new Document([
'installations' => $results,
@ -1389,6 +1401,7 @@ App::get('/v1/vcs/installations/:installationId')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'getInstallation',
description: '/docs/references/vcs/get-installation.md',
auth: [AuthType::ADMIN],
@ -1423,6 +1436,7 @@ App::delete('/v1/vcs/installations/:installationId')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'deleteInstallation',
description: '/docs/references/vcs/delete-installation.md',
auth: [AuthType::ADMIN],
@ -1458,11 +1472,12 @@ App::delete('/v1/vcs/installations/:installationId')
});
App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositoryId')
->desc('Authorize external deployment')
->desc('Update external deployment (authorize)')
->groups(['api', 'vcs'])
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'updateExternalDeployments',
description: '/docs/references/vcs/update-external-deployments.md',
auth: [AuthType::ADMIN],

View file

@ -79,11 +79,18 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', '');
if ($rule->isEmpty()) {
if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '') || $host === System::getEnv('_APP_DOMAIN_SITES', '')) {
$appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
$appDomainFunctions = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
$appDomainSites = System::getEnv('_APP_DOMAIN_SITES', '');
if (!empty($appDomainFunctionsFallback) && \str_ends_with($host, $appDomainFunctionsFallback)) {
$appDomainFunctions = $appDomainFunctionsFallback;
}
if ($host === $appDomainFunctions || $host === $appDomainSites) {
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
}
if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) || \str_ends_with($host, System::getEnv('_APP_DOMAIN_SITES', ''))) {
if (\str_ends_with($host, $appDomainFunctions) || \str_ends_with($host, $appDomainSites)) {
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
$exception->addCTA('Start with this domain', $url . '/console');
@ -142,7 +149,31 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$dbForProject = $getProjectDB($project);
/** @var Document $deployment */
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
if (!empty($rule->getAttribute('deploymentId', ''))) {
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
} else {
// 1.6.x DB schema compatibility
// TODO: Make sure deploymentId is never empty, and remove this code
// Check if site or function; should never be site, but better safe than sorry
// Attempts to use attribute from both schemas (1.6 and 1.7)
$resourceType = $rule->getAttribute('deploymentResourceType', $rule->getAttribute('resourceType', ''));
// ID of site or function
$resourceId = $rule->getAttribute('deploymentResourceId', '');
// Document of site or function
$resource = $resourceType === 'function' ?
Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) :
Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId));
// ID of active deployments
// Attempts to use attribute from both schemas (1.6 and 1.7)
$activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', ''));
// Get deployment document, as intended originally
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId));
}
if ($deployment->getAttribute('resourceType', '') === 'functions') {
$type = 'function';
@ -843,8 +874,17 @@ App::init()
}
$owner = '';
$functionsDomainFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) {
$siteDomain = System::getEnv('_APP_DOMAIN_SITES', '');
if (!empty($functionsDomainFallback) && \str_ends_with($host, $functionsDomainFallback)) {
$functionsDomain = $functionsDomainFallback;
}
if (
(!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) ||
(!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain))
) {
$owner = 'Appwrite';
}
@ -1474,6 +1514,7 @@ App::get('/v1/ping')
->label('event', 'projects.[projectId].ping')
->label('sdk', new Method(
namespace: 'ping',
group: null,
name: 'get',
hide: true,
description: <<<EOT

View file

@ -249,34 +249,36 @@ App::init()
subject: 'keys'
);
if ($dbKey) {
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
if (!$dbKey) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
$dbKey->setAttribute('accessedAt', DateTime::now());
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
$dbKey->setAttribute('accessedAt', DateTime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
$sdkValidator = new WhiteList($servers, true);
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
$sdks = $dbKey->getAttribute('sdks', []);
if (!in_array($sdk, $sdks)) {
$sdks[] = $sdk;
$dbKey->setAttribute('sdks', $sdks);
/** Update access time as well */
$dbKey->setAttribute('accessedAt', Datetime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
$sdkValidator = new WhiteList($servers, true);
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
$sdks = $dbKey->getAttribute('sdks', []);
if (!in_array($sdk, $sdks)) {
$sdks[] = $sdk;
$dbKey->setAttribute('sdks', $sdks);
/** Update access time as well */
$dbKey->setAttribute('accessedAt', Datetime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
}
$queueForAudits->setUser($user);
}
$queueForAudits->setUser($user);
}
} // Admin User Authentication
elseif (($project->getId() === 'console' && !$team->isEmpty() && !$user->isEmpty()) || ($project->getId() !== 'console' && !$user->isEmpty() && $mode === APP_MODE_ADMIN)) {
@ -548,7 +550,7 @@ App::init()
$data = $cache->load($key, $timestamp);
if (!empty($data) && !$cacheLog->isEmpty()) {
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
$parts = explode('/', $cacheLog->getAttribute('resourceType', ''));
$type = $parts[0] ?? null;
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {

View file

@ -49,6 +49,8 @@ use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\Wasabi;
use Utopia\Storage\Storage;
use Utopia\System\System;
use Utopia\Telemetry\Adapter as Telemetry;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
use Utopia\Validator\Hostname;
use Utopia\Validator\WhiteList;
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
@ -466,7 +468,9 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
};
}, ['pools', 'cache']);
App::setResource('cache', function (Group $pools) {
App::setResource('telemetry', fn () => new NoTelemetry());
App::setResource('cache', function (Group $pools, Telemetry $telemetry) {
$list = Config::getParam('pools-cache', []);
$adapters = [];
@ -474,12 +478,15 @@ App::setResource('cache', function (Group $pools) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
->getResource();
}
return new Cache(new Sharding($adapters));
}, ['pools']);
$cache = new Cache(new Sharding($adapters));
$cache->setTelemetry($telemetry);
return $cache;
}, ['pools', 'telemetry']);
App::setResource('redis', function () {
$host = System::getEnv('_APP_REDIS_HOST', 'localhost');

View file

@ -175,7 +175,7 @@ $image = $this->getParam('image', '');
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: <?php echo $organization; ?>/console:5.2.53
image: <?php echo $organization; ?>/console:5.2.58
restart: unless-stopped
networks:
- appwrite
@ -763,34 +763,6 @@ $image = $this->getParam('image', '');
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-worker-stats-usage-dump:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: worker-stats-usage-dump
<<: *x-logging
container_name: appwrite-worker-stats-usage-dump
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-task-scheduler-functions:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: schedule-functions

View file

@ -15,7 +15,6 @@ use Appwrite\Event\Messaging;
use Appwrite\Event\Migration;
use Appwrite\Event\Realtime;
use Appwrite\Event\StatsUsage;
use Appwrite\Event\StatsUsageDump;
use Appwrite\Event\Webhook;
use Appwrite\Platform\Appwrite;
use Executor\Executor;
@ -279,10 +278,6 @@ Server::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
Server::setResource('queueForStatsUsageDump', function (Publisher $publisher) {
return new StatsUsageDump($publisher);
}, ['publisher']);
Server::setResource('queueForDatabase', function (Publisher $publisher) {
return new EventDatabase($publisher);
}, ['publisher']);

View file

@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/worker.php stats-usage-dump $@

View file

@ -53,7 +53,7 @@
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/detector": "0.1.*",
"utopia-php/database": "0.64.*",
"utopia-php/database": "0.66.*",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",

26
composer.lock generated
View file

@ -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": "e7875026636ccec909f9aa4d79091d5b",
"content-hash": "51959289a3f882160f5a9eeb605d41d7",
"packages": [
{
"name": "adhocore/jwt",
@ -3497,16 +3497,16 @@
},
{
"name": "utopia-php/database",
"version": "0.64.2",
"version": "0.66.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd"
"reference": "67d2ab418efba31dc76b3564cf043e2b3f98d027"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/dc9c4a68c93e8bea2dfaa76d1ba308be539998bd",
"reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd",
"url": "https://api.github.com/repos/utopia-php/database/zipball/67d2ab418efba31dc76b3564cf043e2b3f98d027",
"reference": "67d2ab418efba31dc76b3564cf043e2b3f98d027",
"shasum": ""
},
"require": {
@ -3547,9 +3547,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.64.2"
"source": "https://github.com/utopia-php/database/tree/0.66.0"
},
"time": "2025-04-09T07:53:05+00:00"
"time": "2025-04-16T07:10:27+00:00"
},
{
"name": "utopia-php/detector",
@ -4811,16 +4811,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.40.12",
"version": "0.40.15",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "182ec17848f81b78c336379bac94ff92b7a73365"
"reference": "65c708b931b29b3e01c5cc7504a734ce2cc3dc95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/182ec17848f81b78c336379bac94ff92b7a73365",
"reference": "182ec17848f81b78c336379bac94ff92b7a73365",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/65c708b931b29b3e01c5cc7504a734ce2cc3dc95",
"reference": "65c708b931b29b3e01c5cc7504a734ce2cc3dc95",
"shasum": ""
},
"require": {
@ -4856,9 +4856,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.40.12"
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.15"
},
"time": "2025-04-02T23:36:11+00:00"
"time": "2025-04-25T08:50:44+00:00"
},
{
"name": "doctrine/annotations",

View file

@ -206,13 +206,14 @@ services:
- _APP_DATABASE_SHARED_TABLES_V1
- _APP_DATABASE_SHARED_NAMESPACE
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
- _APP_CUSTOM_DOMAIN_DENY_LIST
extra_hosts:
- "host.docker.internal:host-gateway"
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: appwrite/console:5.3.0-sites-rc.40
image: appwrite/console:5.3.0-sites-rc.42
restart: unless-stopped
networks:
- appwrite
@ -848,38 +849,6 @@ services:
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
appwrite-worker-stats-usage-dump:
entrypoint: worker-stats-usage-dump
<<: *x-logging
container_name: appwrite-worker-stats-usage-dump
image: appwrite-dev
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
- _APP_STATS_USAGE_DUAL_WRITING_DBS
appwrite-task-scheduler-functions:
entrypoint: schedule-functions
<<: *x-logging
@ -973,7 +942,7 @@ services:
appwrite-browser:
container_name: appwrite-browser
image: appwrite/browser:0.2.2
image: appwrite/browser:0.2.4
networks:
- appwrite

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Databases databases = new Databases(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Databases databases = new Databases(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Databases databases = new Databases(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Databases databases = new Databases(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Databases databases = new Databases(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);

View file

@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);

Some files were not shown because too many files have changed in this diff Show more