mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge remote-tracking branch 'origin/1.8.x' into feat-health-module
This commit is contained in:
+21
-10
@@ -41,8 +41,6 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
|
||||
// require controllers after overwriting runtimes
|
||||
require_once __DIR__ . '/controllers/general.php';
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
CLI::setResource('register', fn () => $register);
|
||||
|
||||
CLI::setResource('cache', function ($pools) {
|
||||
@@ -60,7 +58,13 @@ CLI::setResource('pools', function (Registry $register) {
|
||||
return $register->get('pools');
|
||||
}, ['register']);
|
||||
|
||||
CLI::setResource('dbForPlatform', function ($pools, $cache) {
|
||||
CLI::setResource('authorization', function () {
|
||||
$authorization = new Authorization();
|
||||
$authorization->disable();
|
||||
return $authorization;
|
||||
}, []);
|
||||
|
||||
CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) {
|
||||
$sleep = 3;
|
||||
$maxAttempts = 5;
|
||||
$attempts = 0;
|
||||
@@ -74,6 +78,8 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) {
|
||||
$dbForPlatform = new Database($adapter, $cache);
|
||||
|
||||
$dbForPlatform
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setNamespace('_console')
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', 'console');
|
||||
@@ -99,7 +105,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) {
|
||||
}
|
||||
|
||||
return $dbForPlatform;
|
||||
}, ['pools', 'cache']);
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
CLI::setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
@@ -110,10 +116,10 @@ CLI::setResource(
|
||||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
|
||||
);
|
||||
|
||||
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
|
||||
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) {
|
||||
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
|
||||
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) {
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -146,6 +152,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
|
||||
|
||||
$adapter = new DatabasePool($pools->get($dsn->getHost()));
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$databases[$dsn->getHost()] = $database;
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
@@ -162,17 +169,19 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
|
||||
}
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId());
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache']);
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'authorization']);
|
||||
|
||||
CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$database = null;
|
||||
|
||||
return function (?Document $project = null) use ($pools, $cache, $database) {
|
||||
return function (?Document $project = null) use ($pools, $cache, $database, $authorization) {
|
||||
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$database->setTenant((int)$project->getSequence());
|
||||
return $database;
|
||||
@@ -182,6 +191,8 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setSharedTables(true)
|
||||
->setNamespace('logsV1')
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK)
|
||||
@@ -194,7 +205,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'cache']);
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
CLI::setResource('publisher', function (Group $pools) {
|
||||
return new BrokerPool(publisher: $pools->get('publisher'));
|
||||
}, ['pools']);
|
||||
|
||||
+3
-3
@@ -60,7 +60,7 @@ return [
|
||||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '20.3.2',
|
||||
'version' => '20.3.3',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -227,7 +227,7 @@ return [
|
||||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '12.0.1',
|
||||
'version' => '13.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite-cli',
|
||||
'enabled' => true,
|
||||
@@ -377,7 +377,7 @@ return [
|
||||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '20.1.0',
|
||||
'version' => '20.1.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.8.0",
|
||||
"version": "1.8.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -140,7 +140,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
@@ -224,12 +225,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -439,7 +442,8 @@
|
||||
"duration": {
|
||||
"type": "integer",
|
||||
"description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.",
|
||||
"x-example": 0
|
||||
"x-example": 0,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,7 +555,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 288,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
@@ -623,7 +627,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 290,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
@@ -747,7 +751,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 291,
|
||||
"weight": 280,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
@@ -887,7 +891,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 292,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
@@ -1011,7 +1015,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 296,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
@@ -1145,7 +1149,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 297,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
@@ -1283,7 +1287,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 289,
|
||||
"weight": 278,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
@@ -1384,7 +1388,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 295,
|
||||
"weight": 284,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
@@ -1483,7 +1487,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 293,
|
||||
"weight": 282,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
@@ -1582,7 +1586,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 294,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
@@ -1796,7 +1800,8 @@
|
||||
"oldPassword": {
|
||||
"type": "string",
|
||||
"description": "Current user password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1868,12 +1873,14 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2072,12 +2079,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2382,12 +2391,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2573,9 +2584,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": []
|
||||
@@ -3304,7 +3313,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3390,12 +3400,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3504,9 +3516,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": []
|
||||
@@ -3621,7 +3631,8 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -3746,7 +3757,8 @@
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -4039,7 +4051,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 50,
|
||||
"weight": 288,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
@@ -4167,7 +4179,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 49,
|
||||
"weight": 287,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
@@ -4301,7 +4313,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 53,
|
||||
"weight": 291,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
@@ -4361,7 +4373,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 51,
|
||||
"weight": 289,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
@@ -4851,7 +4863,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 52,
|
||||
"weight": 290,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
@@ -4935,7 +4947,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 55,
|
||||
"weight": 293,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
@@ -5029,7 +5041,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 54,
|
||||
"weight": 292,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
@@ -5123,7 +5135,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 56,
|
||||
"weight": 294,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
@@ -5980,7 +5992,8 @@
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7146,12 +7159,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7273,12 +7288,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7318,7 +7335,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 454,
|
||||
"weight": 455,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
@@ -7405,7 +7422,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 452,
|
||||
"weight": 453,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
@@ -7523,7 +7540,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 453,
|
||||
"weight": 454,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
@@ -7598,7 +7615,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 225,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
@@ -7652,7 +7669,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 224,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
@@ -7706,7 +7723,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/get.md",
|
||||
@@ -7760,7 +7777,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-codes.md",
|
||||
@@ -7814,7 +7831,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-continents.md",
|
||||
@@ -7868,7 +7885,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries.md",
|
||||
@@ -7922,7 +7939,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-eu.md",
|
||||
@@ -7976,7 +7993,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-phones.md",
|
||||
@@ -8030,7 +8047,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 66,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-currencies.md",
|
||||
@@ -8084,7 +8101,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 67,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-languages.md",
|
||||
@@ -8138,7 +8155,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 272,
|
||||
"weight": 261,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
@@ -8222,7 +8239,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 276,
|
||||
"weight": 265,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
@@ -8298,7 +8315,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 525,
|
||||
"weight": 526,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
@@ -8397,7 +8414,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 523,
|
||||
"weight": 524,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
@@ -8452,7 +8469,8 @@
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "binary"
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
@@ -8498,7 +8516,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 524,
|
||||
"weight": 525,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
@@ -8572,7 +8590,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 526,
|
||||
"weight": 527,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
@@ -8664,7 +8682,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 527,
|
||||
"weight": 528,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
@@ -8733,7 +8751,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 529,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
@@ -8813,7 +8831,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 528,
|
||||
"weight": 529,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
@@ -9043,7 +9061,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 530,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
@@ -9240,7 +9258,8 @@
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10403,12 +10422,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10529,12 +10550,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10574,7 +10597,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 145,
|
||||
"weight": 134,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
@@ -10663,7 +10686,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 144,
|
||||
"weight": 133,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
@@ -10750,7 +10773,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 146,
|
||||
"weight": 135,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
@@ -10814,7 +10837,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 148,
|
||||
"weight": 137,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
@@ -10890,7 +10913,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 150,
|
||||
"weight": 139,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
@@ -10956,7 +10979,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 152,
|
||||
"weight": 141,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
@@ -11055,7 +11078,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 151,
|
||||
"weight": 140,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
@@ -11104,7 +11127,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Email of the new team member.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string",
|
||||
@@ -11114,7 +11138,8 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
@@ -11134,7 +11159,8 @@
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -11175,7 +11201,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 153,
|
||||
"weight": 142,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
@@ -11249,7 +11275,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 154,
|
||||
"weight": 143,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
@@ -11345,7 +11371,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 156,
|
||||
"weight": 145,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
@@ -11421,7 +11447,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 155,
|
||||
"weight": 144,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
@@ -11521,7 +11547,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 147,
|
||||
"weight": 136,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
@@ -11584,7 +11610,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 149,
|
||||
"weight": 138,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -140,7 +140,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
@@ -224,12 +225,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -439,7 +442,8 @@
|
||||
"duration": {
|
||||
"type": "integer",
|
||||
"description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.",
|
||||
"x-example": 0
|
||||
"x-example": 0,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,7 +555,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 288,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
@@ -623,7 +627,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 290,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
@@ -747,7 +751,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 291,
|
||||
"weight": 280,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
@@ -887,7 +891,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 292,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
@@ -1011,7 +1015,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 296,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
@@ -1145,7 +1149,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 297,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
@@ -1283,7 +1287,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 289,
|
||||
"weight": 278,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
@@ -1384,7 +1388,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 295,
|
||||
"weight": 284,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
@@ -1483,7 +1487,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 293,
|
||||
"weight": 282,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
@@ -1582,7 +1586,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 294,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
@@ -1796,7 +1800,8 @@
|
||||
"oldPassword": {
|
||||
"type": "string",
|
||||
"description": "Current user password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1868,12 +1873,14 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2072,12 +2079,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2382,12 +2391,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2573,9 +2584,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": []
|
||||
@@ -3304,7 +3313,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3390,12 +3400,14 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3504,9 +3516,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": []
|
||||
@@ -3621,7 +3631,8 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -3746,7 +3757,8 @@
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -4039,7 +4051,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 50,
|
||||
"weight": 288,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
@@ -4167,7 +4179,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 49,
|
||||
"weight": 287,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
@@ -4301,7 +4313,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 53,
|
||||
"weight": 291,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
@@ -4361,7 +4373,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 51,
|
||||
"weight": 289,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
@@ -4851,7 +4863,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 52,
|
||||
"weight": 290,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
@@ -4935,7 +4947,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 55,
|
||||
"weight": 293,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
@@ -5029,7 +5041,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 54,
|
||||
"weight": 292,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
@@ -5123,7 +5135,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 56,
|
||||
"weight": 294,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
@@ -5980,7 +5992,8 @@
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7146,12 +7159,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7273,12 +7288,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7598,7 +7615,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 225,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
@@ -7652,7 +7669,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 224,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
@@ -7706,7 +7723,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/get.md",
|
||||
@@ -7760,7 +7777,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-codes.md",
|
||||
@@ -7814,7 +7831,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-continents.md",
|
||||
@@ -7868,7 +7885,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries.md",
|
||||
@@ -7922,7 +7939,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-eu.md",
|
||||
@@ -7976,7 +7993,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-phones.md",
|
||||
@@ -8030,7 +8047,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 66,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-currencies.md",
|
||||
@@ -8084,7 +8101,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 67,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-languages.md",
|
||||
@@ -8138,7 +8155,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 272,
|
||||
"weight": 261,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
@@ -8222,7 +8239,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 276,
|
||||
"weight": 265,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
@@ -8452,7 +8469,8 @@
|
||||
"file": {
|
||||
"type": "string",
|
||||
"description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "binary"
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
@@ -9240,7 +9258,8 @@
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10403,12 +10422,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10529,12 +10550,14 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.",
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10574,7 +10597,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 145,
|
||||
"weight": 134,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
@@ -10663,7 +10686,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 144,
|
||||
"weight": 133,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
@@ -10750,7 +10773,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 146,
|
||||
"weight": 135,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
@@ -10814,7 +10837,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 148,
|
||||
"weight": 137,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
@@ -10890,7 +10913,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 150,
|
||||
"weight": 139,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
@@ -10956,7 +10979,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 152,
|
||||
"weight": 141,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
@@ -11055,7 +11078,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 151,
|
||||
"weight": 140,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
@@ -11104,7 +11127,8 @@
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Email of the new team member.",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string",
|
||||
@@ -11114,7 +11138,8 @@
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
@@ -11134,7 +11159,8 @@
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -11175,7 +11201,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 153,
|
||||
"weight": 142,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
@@ -11249,7 +11275,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 154,
|
||||
"weight": 143,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
@@ -11345,7 +11371,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 156,
|
||||
"weight": 145,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
@@ -11421,7 +11447,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 155,
|
||||
"weight": 144,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
@@ -11521,7 +11547,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 147,
|
||||
"weight": 136,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
@@ -11584,7 +11610,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 149,
|
||||
"weight": 138,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
@@ -13428,6 +13454,16 @@
|
||||
"description": "Total number of chunks uploaded",
|
||||
"x-example": 17890,
|
||||
"format": "int32"
|
||||
},
|
||||
"encryption": {
|
||||
"type": "boolean",
|
||||
"description": "Whether file contents are encrypted at rest.",
|
||||
"x-example": true
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
|
||||
"x-example": "gzip"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -13441,7 +13477,9 @@
|
||||
"mimeType",
|
||||
"sizeOriginal",
|
||||
"chunksTotal",
|
||||
"chunksUploaded"
|
||||
"chunksUploaded",
|
||||
"encryption",
|
||||
"compression"
|
||||
],
|
||||
"example": {
|
||||
"$id": "5e5ea5c16897e",
|
||||
@@ -13456,7 +13494,9 @@
|
||||
"mimeType": "image\/png",
|
||||
"sizeOriginal": 17890,
|
||||
"chunksTotal": 17890,
|
||||
"chunksUploaded": 17890
|
||||
"chunksUploaded": 17890,
|
||||
"encryption": true,
|
||||
"compression": "gzip"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.8.0",
|
||||
"version": "1.8.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -191,7 +191,8 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
@@ -280,13 +281,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -498,7 +501,8 @@
|
||||
"type": "integer",
|
||||
"description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.",
|
||||
"default": 900,
|
||||
"x-example": 0
|
||||
"x-example": 0,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -608,7 +612,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 288,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
@@ -683,7 +687,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 290,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
@@ -807,7 +811,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 291,
|
||||
"weight": 280,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
@@ -948,7 +952,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 292,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
@@ -1072,7 +1076,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 296,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
@@ -1209,7 +1213,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 297,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
@@ -1349,7 +1353,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 289,
|
||||
"weight": 278,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
@@ -1450,7 +1454,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 295,
|
||||
"weight": 284,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
@@ -1551,7 +1555,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 293,
|
||||
"weight": 282,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
@@ -1652,7 +1656,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 294,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
@@ -1874,7 +1878,8 @@
|
||||
"type": "string",
|
||||
"description": "Current user password. Must be at least 8 chars.",
|
||||
"default": "",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1949,13 +1954,15 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": null,
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2160,13 +2167,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": null,
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2485,13 +2494,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2683,9 +2694,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": [],
|
||||
@@ -3429,7 +3438,8 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3520,13 +3530,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": "",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3638,9 +3650,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": [],
|
||||
@@ -3754,7 +3764,8 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": null,
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -3882,7 +3893,8 @@
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": null,
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -4191,7 +4203,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 50,
|
||||
"weight": 288,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
@@ -4317,7 +4329,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 49,
|
||||
"weight": 287,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
@@ -4449,7 +4461,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 53,
|
||||
"weight": 291,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
@@ -4513,7 +4525,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 51,
|
||||
"weight": 289,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
@@ -5001,7 +5013,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 52,
|
||||
"weight": 290,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
@@ -5085,7 +5097,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 55,
|
||||
"weight": 293,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
@@ -5177,7 +5189,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 54,
|
||||
"weight": 292,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
@@ -5269,7 +5281,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 56,
|
||||
"weight": 294,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
@@ -6087,7 +6099,8 @@
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"default": 300,
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7208,13 +7221,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7329,13 +7344,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7375,7 +7392,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 454,
|
||||
"weight": 455,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
@@ -7458,7 +7475,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 452,
|
||||
"weight": 453,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
@@ -7577,7 +7594,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 453,
|
||||
"weight": 454,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
@@ -7649,7 +7666,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 225,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
@@ -7724,7 +7741,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 224,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
@@ -7797,7 +7814,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/get.md",
|
||||
@@ -7850,7 +7867,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-codes.md",
|
||||
@@ -7903,7 +7920,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-continents.md",
|
||||
@@ -7956,7 +7973,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries.md",
|
||||
@@ -8009,7 +8026,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-eu.md",
|
||||
@@ -8062,7 +8079,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-phones.md",
|
||||
@@ -8115,7 +8132,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 66,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-currencies.md",
|
||||
@@ -8168,7 +8185,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 67,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-languages.md",
|
||||
@@ -8223,7 +8240,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 272,
|
||||
"weight": 261,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
@@ -8308,7 +8325,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 276,
|
||||
"weight": 265,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
@@ -8379,7 +8396,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 525,
|
||||
"weight": 526,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
@@ -8472,7 +8489,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 523,
|
||||
"weight": 524,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
@@ -8563,7 +8580,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 524,
|
||||
"weight": 525,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
@@ -8634,7 +8651,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 526,
|
||||
"weight": 527,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
@@ -8725,7 +8742,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 527,
|
||||
"weight": 528,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
@@ -8796,7 +8813,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 529,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
@@ -8876,7 +8893,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 528,
|
||||
"weight": 529,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
@@ -9084,7 +9101,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 530,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
@@ -9275,7 +9292,8 @@
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"default": 300,
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10393,13 +10411,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10513,13 +10533,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10559,7 +10581,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 145,
|
||||
"weight": 134,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
@@ -10644,7 +10666,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 144,
|
||||
"weight": 133,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
@@ -10735,7 +10757,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 146,
|
||||
"weight": 135,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
@@ -10798,7 +10820,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 148,
|
||||
"weight": 137,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
@@ -10874,7 +10896,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 150,
|
||||
"weight": 139,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
@@ -10937,7 +10959,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 152,
|
||||
"weight": 141,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
@@ -11030,7 +11052,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 151,
|
||||
"weight": 140,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
@@ -11076,7 +11098,8 @@
|
||||
"type": "string",
|
||||
"description": "Email of the new team member.",
|
||||
"default": "",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string",
|
||||
@@ -11088,7 +11111,8 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": "",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
@@ -11110,7 +11134,8 @@
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": "",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -11151,7 +11176,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 153,
|
||||
"weight": 142,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
@@ -11222,7 +11247,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 154,
|
||||
"weight": 143,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
@@ -11316,7 +11341,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 156,
|
||||
"weight": 145,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
@@ -11389,7 +11414,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 155,
|
||||
"weight": 144,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
@@ -11485,7 +11510,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 147,
|
||||
"weight": 136,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
@@ -11548,7 +11573,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 149,
|
||||
"weight": 138,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -191,7 +191,8 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
@@ -280,13 +281,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -498,7 +501,8 @@
|
||||
"type": "integer",
|
||||
"description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.",
|
||||
"default": 900,
|
||||
"x-example": 0
|
||||
"x-example": 0,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -608,7 +612,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 288,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
@@ -683,7 +687,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 290,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
@@ -807,7 +811,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 291,
|
||||
"weight": 280,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
@@ -948,7 +952,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 292,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
@@ -1072,7 +1076,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 296,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
@@ -1209,7 +1213,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 297,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
@@ -1349,7 +1353,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 289,
|
||||
"weight": 278,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
@@ -1450,7 +1454,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 295,
|
||||
"weight": 284,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
@@ -1551,7 +1555,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 293,
|
||||
"weight": 282,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
@@ -1652,7 +1656,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 294,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
@@ -1874,7 +1878,8 @@
|
||||
"type": "string",
|
||||
"description": "Current user password. Must be at least 8 chars.",
|
||||
"default": "",
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1949,13 +1954,15 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": null,
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2160,13 +2167,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": null,
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2485,13 +2494,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "User password. Must be at least 8 chars.",
|
||||
"default": null,
|
||||
"x-example": "password"
|
||||
"x-example": "password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2683,9 +2694,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": [],
|
||||
@@ -3429,7 +3438,8 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3520,13 +3530,15 @@
|
||||
"type": "string",
|
||||
"description": "User email.",
|
||||
"default": null,
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": "",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"phrase": {
|
||||
"type": "boolean",
|
||||
@@ -3638,9 +3650,7 @@
|
||||
"yammer",
|
||||
"yandex",
|
||||
"zoho",
|
||||
"zoom",
|
||||
"mock",
|
||||
"mock-unverified"
|
||||
"zoom"
|
||||
],
|
||||
"x-enum-name": "OAuthProvider",
|
||||
"x-enum-keys": [],
|
||||
@@ -3754,7 +3764,8 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": null,
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -3882,7 +3893,8 @@
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": null,
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -4191,7 +4203,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 50,
|
||||
"weight": 288,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
@@ -4317,7 +4329,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 49,
|
||||
"weight": 287,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
@@ -4449,7 +4461,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 53,
|
||||
"weight": 291,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
@@ -4513,7 +4525,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 51,
|
||||
"weight": 289,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
@@ -5001,7 +5013,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 52,
|
||||
"weight": 290,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
@@ -5085,7 +5097,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 55,
|
||||
"weight": 293,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
@@ -5177,7 +5189,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 54,
|
||||
"weight": 292,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
@@ -5269,7 +5281,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 56,
|
||||
"weight": 294,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
@@ -6087,7 +6099,8 @@
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"default": 300,
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7208,13 +7221,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7329,13 +7344,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the attribute by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -7649,7 +7666,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 225,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
@@ -7724,7 +7741,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 224,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
@@ -7797,7 +7814,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/get.md",
|
||||
@@ -7850,7 +7867,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-codes.md",
|
||||
@@ -7903,7 +7920,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-continents.md",
|
||||
@@ -7956,7 +7973,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries.md",
|
||||
@@ -8009,7 +8026,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-eu.md",
|
||||
@@ -8062,7 +8079,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-countries-phones.md",
|
||||
@@ -8115,7 +8132,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 66,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-currencies.md",
|
||||
@@ -8168,7 +8185,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 67,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "locale\/list-languages.md",
|
||||
@@ -8223,7 +8240,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 272,
|
||||
"weight": 261,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
@@ -8308,7 +8325,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 276,
|
||||
"weight": 265,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
@@ -9275,7 +9292,8 @@
|
||||
"type": "integer",
|
||||
"description": "Seconds before the transaction expires.",
|
||||
"default": 300,
|
||||
"x-example": 60
|
||||
"x-example": 60,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10393,13 +10411,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"min": {
|
||||
"type": "number",
|
||||
"description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10513,13 +10533,15 @@
|
||||
"type": "number",
|
||||
"description": "Value to increment the column by. The value must be a number.",
|
||||
"default": 1,
|
||||
"x-example": null
|
||||
"x-example": null,
|
||||
"format": "float"
|
||||
},
|
||||
"max": {
|
||||
"type": "number",
|
||||
"description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"format": "float",
|
||||
"x-nullable": true
|
||||
},
|
||||
"transactionId": {
|
||||
@@ -10559,7 +10581,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 145,
|
||||
"weight": 134,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
@@ -10644,7 +10666,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 144,
|
||||
"weight": 133,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
@@ -10735,7 +10757,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 146,
|
||||
"weight": 135,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
@@ -10798,7 +10820,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 148,
|
||||
"weight": 137,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
@@ -10874,7 +10896,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 150,
|
||||
"weight": 139,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
@@ -10937,7 +10959,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 152,
|
||||
"weight": 141,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
@@ -11030,7 +11052,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 151,
|
||||
"weight": 140,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
@@ -11076,7 +11098,8 @@
|
||||
"type": "string",
|
||||
"description": "Email of the new team member.",
|
||||
"default": "",
|
||||
"x-example": "email@example.com"
|
||||
"x-example": "email@example.com",
|
||||
"format": "email"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string",
|
||||
@@ -11088,7 +11111,8 @@
|
||||
"type": "string",
|
||||
"description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.",
|
||||
"default": "",
|
||||
"x-example": "+12065550100"
|
||||
"x-example": "+12065550100",
|
||||
"format": "phone"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
@@ -11110,7 +11134,8 @@
|
||||
"type": "string",
|
||||
"description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.",
|
||||
"default": "",
|
||||
"x-example": "https:\/\/example.com"
|
||||
"x-example": "https:\/\/example.com",
|
||||
"format": "url"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -11151,7 +11176,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 153,
|
||||
"weight": 142,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
@@ -11222,7 +11247,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 154,
|
||||
"weight": 143,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
@@ -11316,7 +11341,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 156,
|
||||
"weight": 145,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
@@ -11389,7 +11414,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 155,
|
||||
"weight": 144,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
@@ -11485,7 +11510,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 147,
|
||||
"weight": 136,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
@@ -11548,7 +11573,7 @@
|
||||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 149,
|
||||
"weight": 138,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
@@ -13368,6 +13393,16 @@
|
||||
"description": "Total number of chunks uploaded",
|
||||
"x-example": 17890,
|
||||
"format": "int32"
|
||||
},
|
||||
"encryption": {
|
||||
"type": "boolean",
|
||||
"description": "Whether file contents are encrypted at rest.",
|
||||
"x-example": true
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"description": "Compression algorithm used for the file. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).",
|
||||
"x-example": "gzip"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -13381,7 +13416,9 @@
|
||||
"mimeType",
|
||||
"sizeOriginal",
|
||||
"chunksTotal",
|
||||
"chunksUploaded"
|
||||
"chunksUploaded",
|
||||
"encryption",
|
||||
"compression"
|
||||
],
|
||||
"example": {
|
||||
"$id": "5e5ea5c16897e",
|
||||
@@ -13396,7 +13433,9 @@
|
||||
"mimeType": "image\/png",
|
||||
"sizeOriginal": 17890,
|
||||
"chunksTotal": 17890,
|
||||
"chunksUploaded": 17890
|
||||
"chunksUploaded": 17890,
|
||||
"encryption": true,
|
||||
"compression": "gzip"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,4 +3,6 @@
|
||||
use Utopia\Image\Image;
|
||||
use Utopia\System\System;
|
||||
|
||||
Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64)));
|
||||
if (\class_exists('Imagick')) {
|
||||
Image::setResourceLimit('memory', intval(System::getEnv('_APP_IMAGES_RESOURCE_LIMIT_MEMORY', 1024*1024*64)));
|
||||
}
|
||||
|
||||
@@ -207,10 +207,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr
|
||||
}
|
||||
|
||||
|
||||
$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) {
|
||||
$createSession = function (string $userId, string $secret, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode, Authorization $authorization) {
|
||||
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $userFromRequest */
|
||||
$userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
$userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($userFromRequest->isEmpty()) {
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
@@ -266,7 +266,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$session = $dbForProject->createDocument('sessions', $session
|
||||
->setAttribute('$permissions', [
|
||||
@@ -275,7 +275,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId()));
|
||||
$authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId()));
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
// Magic URL + Email OTP
|
||||
@@ -376,8 +376,9 @@ App::post('/v1/account')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('hooks')
|
||||
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Hooks $hooks) {
|
||||
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Hooks $hooks) {
|
||||
|
||||
$email = \strtolower($email);
|
||||
if ('console' === $project->getId()) {
|
||||
@@ -469,9 +470,9 @@ App::post('/v1/account')
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
$user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
try {
|
||||
$target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
$target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
Permission::update(Role::user($user->getId())),
|
||||
@@ -497,9 +498,9 @@ App::post('/v1/account')
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
Authorization::unsetRole(Role::guests()->toString());
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
Authorization::setRole(Role::users()->toString());
|
||||
$authorization->removeRole(Role::guests()->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::users()->toString());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
@@ -976,7 +977,8 @@ App::post('/v1/account/sessions/email')
|
||||
->inject('store')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $email, string $password, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
$email = \strtolower($email);
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
@@ -1021,7 +1023,7 @@ App::post('/v1/account/sessions/email')
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
// Re-hash if not using recommended algo
|
||||
if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) {
|
||||
@@ -1120,7 +1122,8 @@ App::post('/v1/account/sessions/anonymous')
|
||||
->inject('store')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (Request $request, Response $response, Locale $locale, User $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
if ('console' === $project->getId()) {
|
||||
@@ -1165,7 +1168,7 @@ App::post('/v1/account/sessions/anonymous')
|
||||
'accessedAt' => DateTime::now(),
|
||||
]);
|
||||
$user->removeAttribute('$sequence');
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
|
||||
// Create session token
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
@@ -1191,7 +1194,7 @@ App::post('/v1/account/sessions/anonymous')
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
@@ -1274,6 +1277,7 @@ App::post('/v1/account/sessions/token')
|
||||
->inject('store')
|
||||
->inject('proofForToken')
|
||||
->inject('proofForCode')
|
||||
->inject('authorization')
|
||||
->action($createSession);
|
||||
|
||||
App::get('/v1/account/sessions/oauth2/:provider')
|
||||
@@ -1470,7 +1474,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
->inject('store')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) {
|
||||
->inject('authorization')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) {
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https';
|
||||
$port = $request->getPort();
|
||||
$callbackBase = $protocol . '://' . $request->getHostname();
|
||||
@@ -1726,7 +1731,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
$userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$userDoc = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$dbForProject->createDocument('targets', new Document([
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
@@ -1744,8 +1749,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
}
|
||||
}
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
Authorization::setRole(Role::users()->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::users()->toString());
|
||||
|
||||
if (false === $user->getAttribute('status')) { // Account is blocked
|
||||
$failureRedirect(Exception::USER_BLOCKED); // User is in status blocked
|
||||
@@ -1816,7 +1821,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
|
||||
$dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$state['success'] = URLParser::parse($state['success']);
|
||||
$query = URLParser::parseQuery($state['success']['query']);
|
||||
@@ -1840,7 +1845,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$token = $dbForProject->createDocument('tokens', $token
|
||||
->setAttribute('$permissions', [
|
||||
@@ -2077,7 +2082,8 @@ App::post('/v1/account/tokens/magic-url')
|
||||
->inject('queueForMails')
|
||||
->inject('proofForPassword')
|
||||
->inject('platform')
|
||||
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, array $platform, Authorization $authorization) {
|
||||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
@@ -2150,7 +2156,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
}
|
||||
|
||||
$proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL);
|
||||
@@ -2170,7 +2176,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$token = $dbForProject->createDocument('tokens', $token
|
||||
->setAttribute('$permissions', [
|
||||
@@ -2356,7 +2362,8 @@ App::post('/v1/account/tokens/email')
|
||||
->inject('queueForMails')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForCode')
|
||||
->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode, Authorization $authorization) {
|
||||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
@@ -2425,9 +2432,9 @@ App::post('/v1/account/tokens/email')
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
$user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
try {
|
||||
$target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
$target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
Permission::update(Role::user($user->getId())),
|
||||
@@ -2465,7 +2472,7 @@ App::post('/v1/account/tokens/email')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$token = $dbForProject->createDocument('tokens', $token
|
||||
->setAttribute('$permissions', [
|
||||
@@ -2662,10 +2669,11 @@ App::put('/v1/account/sessions/magic-url')
|
||||
->inject('queueForMails')
|
||||
->inject('store')
|
||||
->inject('proofForCode')
|
||||
->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) {
|
||||
->inject('authorization')
|
||||
->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode, $authorization) use ($createSession) {
|
||||
$proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL);
|
||||
$proofForToken->setHash(new Sha());
|
||||
$createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode);
|
||||
$createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $platform, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode, $authorization);
|
||||
});
|
||||
|
||||
App::put('/v1/account/sessions/phone')
|
||||
@@ -2711,6 +2719,7 @@ App::put('/v1/account/sessions/phone')
|
||||
->inject('store')
|
||||
->inject('proofForToken')
|
||||
->inject('proofForCode')
|
||||
->inject('authorization')
|
||||
->action($createSession);
|
||||
|
||||
App::post('/v1/account/tokens/phone')
|
||||
@@ -2754,7 +2763,8 @@ App::post('/v1/account/tokens/phone')
|
||||
->inject('plan')
|
||||
->inject('store')
|
||||
->inject('proofForCode')
|
||||
->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $phone, Request $request, Response $response, User $user, Document $project, array $platform, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode, Authorization $authorization) {
|
||||
if (empty(System::getEnv('_APP_SMS_PROVIDER'))) {
|
||||
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
|
||||
}
|
||||
@@ -2804,9 +2814,9 @@ App::post('/v1/account/tokens/phone')
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
try {
|
||||
$target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
$target = $authorization->skip(fn () => $dbForProject->createDocument('targets', new Document([
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
Permission::update(Role::user($user->getId())),
|
||||
@@ -2852,7 +2862,7 @@ App::post('/v1/account/tokens/phone')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$token = $dbForProject->createDocument('tokens', $token
|
||||
->setAttribute('$permissions', [
|
||||
@@ -3243,7 +3253,8 @@ App::patch('/v1/account/email')
|
||||
->inject('project')
|
||||
->inject('hooks')
|
||||
->inject('proofForPassword')
|
||||
->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) {
|
||||
->inject('authorization')
|
||||
->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) {
|
||||
// passwordUpdate will be empty if the user has never set a password
|
||||
$passwordUpdate = $user->getAttribute('passwordUpdate');
|
||||
|
||||
@@ -3295,7 +3306,7 @@ App::patch('/v1/account/email')
|
||||
->setAttribute('passwordUpdate', DateTime::now());
|
||||
}
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->findOne('targets', [
|
||||
$target = $authorization->skip(fn () => $dbForProject->findOne('targets', [
|
||||
Query::equal('identifier', [$email]),
|
||||
]));
|
||||
|
||||
@@ -3311,7 +3322,7 @@ App::patch('/v1/account/email')
|
||||
$oldTarget = $user->find('identifier', $oldEmail, 'targets');
|
||||
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email)));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email)));
|
||||
}
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate) {
|
||||
@@ -3352,8 +3363,9 @@ App::patch('/v1/account/phone')
|
||||
->inject('queueForEvents')
|
||||
->inject('project')
|
||||
->inject('hooks')
|
||||
->inject('proofForPassword')
|
||||
->action(function (string $phone, string $password, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) {
|
||||
->inject('proofForPassword')
|
||||
->inject('authorization')
|
||||
->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword, Authorization $authorization) {
|
||||
// passwordUpdate will be empty if the user has never set a password
|
||||
$passwordUpdate = $user->getAttribute('passwordUpdate');
|
||||
|
||||
@@ -3368,7 +3380,7 @@ App::patch('/v1/account/phone')
|
||||
|
||||
$hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]);
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->findOne('targets', [
|
||||
$target = $authorization->skip(fn () => $dbForProject->findOne('targets', [
|
||||
Query::equal('identifier', [$phone]),
|
||||
]));
|
||||
|
||||
@@ -3399,7 +3411,7 @@ App::patch('/v1/account/phone')
|
||||
$oldTarget = $user->find('identifier', $oldPhone, 'targets');
|
||||
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone)));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone)));
|
||||
}
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate $th) {
|
||||
@@ -3535,7 +3547,9 @@ App::post('/v1/account/recovery')
|
||||
->inject('queueForMails')
|
||||
->inject('queueForEvents')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $email, string $url, Request $request, Response $response, User $user, Database $dbForProject, Document $project, array $platform, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
|
||||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
}
|
||||
@@ -3571,7 +3585,7 @@ App::post('/v1/account/recovery')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($profile->getId())->toString());
|
||||
$authorization->addRole(Role::user($profile->getId())->toString());
|
||||
|
||||
$recovery = $dbForProject->createDocument('tokens', $recovery
|
||||
->setAttribute('$permissions', [
|
||||
@@ -3727,7 +3741,8 @@ App::put('/v1/account/recovery')
|
||||
->inject('hooks')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $secret, string $password, Response $response, User $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $profile */
|
||||
$profile = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
@@ -3741,7 +3756,7 @@ App::put('/v1/account/recovery')
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole(Role::user($profile->getId())->toString());
|
||||
$authorization->addRole(Role::user($profile->getId())->toString());
|
||||
|
||||
$newPassword = $proofForPassword->hash($password);
|
||||
|
||||
@@ -3844,7 +3859,8 @@ App::post('/v1/account/verifications/email')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $url, Request $request, Response $response, Document $project, array $platform, User $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
|
||||
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
@@ -3873,7 +3889,7 @@ App::post('/v1/account/verifications/email')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$verification = $dbForProject->createDocument('tokens', $verification
|
||||
->setAttribute('$permissions', [
|
||||
@@ -4072,9 +4088,10 @@ App::put('/v1/account/verifications/email')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $profile */
|
||||
$profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
$profile = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -4086,7 +4103,7 @@ App::put('/v1/account/verifications/email')
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole(Role::user($profile->getId())->toString());
|
||||
$authorization->addRole(Role::user($profile->getId())->toString());
|
||||
|
||||
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true));
|
||||
|
||||
@@ -4146,7 +4163,8 @@ App::post('/v1/account/verifications/phone')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('plan')
|
||||
->inject('proofForCode')
|
||||
->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) {
|
||||
->inject('authorization')
|
||||
->action(function (Request $request, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode, Authorization $authorization) {
|
||||
if (empty(System::getEnv('_APP_SMS_PROVIDER'))) {
|
||||
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
|
||||
}
|
||||
@@ -4185,7 +4203,7 @@ App::post('/v1/account/verifications/phone')
|
||||
'ip' => $request->getIP(),
|
||||
]);
|
||||
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$verification = $dbForProject->createDocument('tokens', $verification
|
||||
->setAttribute('$permissions', [
|
||||
@@ -4291,9 +4309,10 @@ App::put('/v1/account/verifications/phone')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('proofForCode')
|
||||
->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) {
|
||||
->inject('authorization')
|
||||
->action(function (string $userId, string $secret, Response $response, User $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode, Authorization $authorization) {
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $profile */
|
||||
$profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
$profile = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -4305,7 +4324,7 @@ App::put('/v1/account/verifications/phone')
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole(Role::user($profile->getId())->toString());
|
||||
$authorization->addRole(Role::user($profile->getId())->toString());
|
||||
|
||||
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true));
|
||||
|
||||
@@ -4358,12 +4377,13 @@ App::post('/v1/account/targets/push')
|
||||
->inject('dbForProject')
|
||||
->inject('store')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) {
|
||||
->inject('authorization')
|
||||
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, User $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken, Authorization $authorization) {
|
||||
$targetId = $targetId == 'unique()' ? ID::unique() : $targetId;
|
||||
|
||||
$provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId));
|
||||
$provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId));
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
|
||||
if (!$target->isEmpty()) {
|
||||
throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS);
|
||||
@@ -4438,9 +4458,10 @@ App::put('/v1/account/targets/:targetId/push')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) {
|
||||
->inject('authorization')
|
||||
->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) {
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
|
||||
if ($target->isEmpty()) {
|
||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||
@@ -4503,8 +4524,9 @@ App::delete('/v1/account/targets/:targetId/push')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) {
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
->inject('authorization')
|
||||
->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) {
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
|
||||
if ($target->isEmpty()) {
|
||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||
|
||||
@@ -28,11 +28,12 @@ use Utopia\Validator\Text;
|
||||
App::init()
|
||||
->groups(['graphql'])
|
||||
->inject('project')
|
||||
->action(function (Document $project) {
|
||||
->inject('authorization')
|
||||
->action(function (Document $project, Authorization $authorization) {
|
||||
if (
|
||||
array_key_exists('graphql', $project->getAttribute('apis', []))
|
||||
&& !$project->getAttribute('apis', [])['graphql']
|
||||
&& !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles()))
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Authorization\Input;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Validator\Queries;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
@@ -1073,8 +1074,9 @@ App::get('/v1/messaging/providers')
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) {
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
@@ -1100,7 +1102,7 @@ App::get('/v1/messaging/providers')
|
||||
}
|
||||
|
||||
$providerId = $cursor->getValue();
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId));
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId));
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Provider '{$providerId}' for the 'cursor' value not found.");
|
||||
@@ -2481,8 +2483,9 @@ App::get('/v1/messaging/topics')
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) {
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
@@ -2508,7 +2511,7 @@ App::get('/v1/messaging/topics')
|
||||
}
|
||||
|
||||
$topicId = $cursor->getValue();
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Topic '{$topicId}' for the 'cursor' value not found.");
|
||||
@@ -2782,29 +2785,27 @@ App::post('/v1/messaging/topics/:topicId/subscribers')
|
||||
->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
$subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId;
|
||||
|
||||
$topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
$topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
throw new Exception(Exception::TOPIC_NOT_FOUND);
|
||||
}
|
||||
|
||||
$validator = new Authorization('subscribe');
|
||||
|
||||
if (!$validator->isValid($topic->getAttribute('subscribe'))) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription());
|
||||
if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription());
|
||||
}
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $targetId));
|
||||
|
||||
if ($target->isEmpty()) {
|
||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
$user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
|
||||
$subscriber = new Document([
|
||||
'$id' => $subscriberId,
|
||||
@@ -2837,7 +2838,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers')
|
||||
default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE),
|
||||
};
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute(
|
||||
$authorization->skip(fn () => $dbForProject->increaseDocumentAttribute(
|
||||
'topics',
|
||||
$topicId,
|
||||
$totalAttribute,
|
||||
@@ -2882,8 +2883,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) {
|
||||
->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
@@ -2894,7 +2896,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
|
||||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
$topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
$topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
throw new Exception(Exception::TOPIC_NOT_FOUND);
|
||||
@@ -2917,7 +2919,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
|
||||
}
|
||||
|
||||
$subscriberId = $cursor->getValue();
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId));
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId));
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Subscriber '{$subscriberId}' for the 'cursor' value not found.");
|
||||
@@ -2931,10 +2933,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
|
||||
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) {
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId')));
|
||||
$user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
$subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $authorization) {
|
||||
return function () use ($subscriber, $dbForProject, $authorization) {
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId')));
|
||||
$user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
|
||||
return $subscriber
|
||||
->setAttribute('target', $target)
|
||||
@@ -3067,9 +3069,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
||||
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
|
||||
->param('subscriberId', '', new UID(), 'Subscriber ID.')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) {
|
||||
$topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
->action(function (string $topicId, string $subscriberId, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
$topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
throw new Exception(Exception::TOPIC_NOT_FOUND);
|
||||
@@ -3081,8 +3084,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
||||
throw new Exception(Exception::SUBSCRIBER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId')));
|
||||
$user = Authorization::skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
$target = $authorization->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId')));
|
||||
$user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
|
||||
|
||||
$subscriber
|
||||
->setAttribute('target', $target)
|
||||
@@ -3118,9 +3121,10 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
||||
->param('subscriberId', '', new UID(), 'Subscriber ID.')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
$topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId));
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
throw new Exception(Exception::TOPIC_NOT_FOUND);
|
||||
@@ -3143,7 +3147,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
||||
default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE),
|
||||
};
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute(
|
||||
$authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute(
|
||||
'topics',
|
||||
$topicId,
|
||||
$totalAttribute,
|
||||
@@ -3702,8 +3706,9 @@ App::get('/v1/messaging/messages')
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) {
|
||||
->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) {
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
@@ -3729,7 +3734,7 @@ App::get('/v1/messaging/messages')
|
||||
}
|
||||
|
||||
$messageId = $cursor->getValue();
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId));
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('messages', $messageId));
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Message '{$messageId}' for the 'cursor' value not found.");
|
||||
|
||||
@@ -342,6 +342,7 @@ App::post('/v1/migrations/csv/imports')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->inject('authorization')
|
||||
->inject('project')
|
||||
->inject('platform')
|
||||
->inject('deviceForFiles')
|
||||
@@ -356,6 +357,7 @@ App::post('/v1/migrations/csv/imports')
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Database $dbForPlatform,
|
||||
Authorization $authorization,
|
||||
Document $project,
|
||||
array $platform,
|
||||
Device $deviceForFiles,
|
||||
@@ -363,7 +365,7 @@ App::post('/v1/migrations/csv/imports')
|
||||
Event $queueForEvents,
|
||||
Migration $queueForMigrations
|
||||
) {
|
||||
$bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) {
|
||||
$bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) {
|
||||
if ($internalFile) {
|
||||
return $dbForPlatform->getDocument('buckets', 'default');
|
||||
}
|
||||
@@ -374,7 +376,7 @@ App::post('/v1/migrations/csv/imports')
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
$file = $authorization->skip(fn () => $internalFile ? $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $fileId) : $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
@@ -491,6 +493,7 @@ App::post('/v1/migrations/csv/exports')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->inject('authorization')
|
||||
->inject('project')
|
||||
->inject('platform')
|
||||
->inject('queueForEvents')
|
||||
@@ -509,6 +512,7 @@ App::post('/v1/migrations/csv/exports')
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Database $dbForPlatform,
|
||||
Authorization $authorization,
|
||||
Document $project,
|
||||
array $platform,
|
||||
Event $queueForEvents,
|
||||
@@ -520,7 +524,7 @@ App::post('/v1/migrations/csv/exports')
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'default'));
|
||||
$bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'default'));
|
||||
if ($bucket->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
@@ -533,12 +537,12 @@ App::post('/v1/migrations/csv/exports')
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -45,9 +45,10 @@ App::get('/v1/project/usage')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('getLogsDB')
|
||||
->inject('smsRates')
|
||||
->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) {
|
||||
->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, Authorization $authorization, callable $getLogsDB, array $smsRates) {
|
||||
$stats = $total = $usage = [];
|
||||
$format = 'Y-m-d 00:00:00';
|
||||
$firstDay = (new DateTime($startDate))->format($format);
|
||||
@@ -102,7 +103,7 @@ App::get('/v1/project/usage')
|
||||
'1d' => 'Y-m-d\T00:00:00.000P',
|
||||
};
|
||||
|
||||
Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) {
|
||||
$authorization->skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) {
|
||||
foreach ($metrics['total'] as $metric) {
|
||||
$db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject;
|
||||
|
||||
@@ -286,7 +287,7 @@ App::get('/v1/project/usage')
|
||||
}, $dbForProject->find('functions'));
|
||||
|
||||
// This total is includes free and paid SMS usage
|
||||
$authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [
|
||||
$authPhoneTotal = $authorization->skip(fn () => $dbForProject->sum('stats', 'value', [
|
||||
Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]),
|
||||
Query::equal('period', ['1d']),
|
||||
Query::greaterThanEqual('time', $firstDay),
|
||||
@@ -294,7 +295,7 @@ App::get('/v1/project/usage')
|
||||
]));
|
||||
|
||||
// This estimate is only for paid SMS usage
|
||||
$authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [
|
||||
$authPhoneMetrics = $authorization->skip(fn () => $dbForProject->find('stats', [
|
||||
Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'),
|
||||
Query::equal('period', ['1d']),
|
||||
Query::greaterThanEqual('time', $firstDay),
|
||||
|
||||
@@ -227,6 +227,7 @@ App::post('/v1/projects')
|
||||
if (!$sharedTablesV2) {
|
||||
$adapter = new DatabasePool($pools->get($dsn->getHost()));
|
||||
$dbForProject = new Database($adapter, $cache);
|
||||
$dbForProject->setDatabase(APP_DATABASE);
|
||||
|
||||
if ($sharedTables) {
|
||||
$dbForProject
|
||||
|
||||
@@ -86,16 +86,17 @@ App::post('/v1/teams')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) {
|
||||
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAppUser = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
|
||||
$teamId = $teamId == 'unique()' ? ID::unique() : $teamId;
|
||||
|
||||
try {
|
||||
$team = Authorization::skip(fn () => $dbForProject->createDocument('teams', new Document([
|
||||
$team = $authorization->skip(fn () => $dbForProject->createDocument('teams', new Document([
|
||||
'$id' => $teamId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::team($teamId)),
|
||||
@@ -491,6 +492,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('locale')
|
||||
->inject('queueForMails')
|
||||
->inject('queueForMessaging')
|
||||
@@ -500,9 +502,9 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
->inject('plan')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) {
|
||||
$isAppUser = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) {
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$url = htmlentities($url);
|
||||
if (empty($url)) {
|
||||
@@ -619,13 +621,13 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
]);
|
||||
|
||||
try {
|
||||
$invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument));
|
||||
$invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', $userDocument));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
$isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team');
|
||||
@@ -661,11 +663,11 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
]);
|
||||
|
||||
$membership = ($isPrivilegedUser || $isAppUser) ?
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) :
|
||||
$authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) :
|
||||
$dbForProject->createDocument('memberships', $membership);
|
||||
|
||||
if ($isPrivilegedUser || $isAppUser) {
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
$authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
}
|
||||
} elseif ($membership->getAttribute('confirm') === false) {
|
||||
$membership->setAttribute('secret', $proofForToken->hash($secret));
|
||||
@@ -677,7 +679,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
}
|
||||
|
||||
$membership = ($isPrivilegedUser || $isAppUser) ?
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) :
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) :
|
||||
$dbForProject->updateDocument('memberships', $membership->getId(), $membership);
|
||||
} else {
|
||||
throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED);
|
||||
@@ -863,7 +865,8 @@ App::get('/v1/teams/:teamId/memberships')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) {
|
||||
->inject('authorization')
|
||||
->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) {
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
@@ -933,7 +936,7 @@ App::get('/v1/teams/:teamId/memberships')
|
||||
'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true,
|
||||
];
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
|
||||
@@ -1004,7 +1007,8 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject) {
|
||||
->inject('authorization')
|
||||
->action(function (string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) {
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
@@ -1024,7 +1028,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
|
||||
'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true,
|
||||
];
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
|
||||
@@ -1103,8 +1107,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) {
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
@@ -1121,9 +1126,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAppUser = User::isApp(Authorization::getRoles());
|
||||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if ($project->getId() === 'console') {
|
||||
// Quick check: fetch up to 2 owners to determine if only one exists
|
||||
@@ -1204,12 +1209,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('project')
|
||||
->inject('geodb')
|
||||
->inject('queueForEvents')
|
||||
->inject('store')
|
||||
->inject('proofForToken')
|
||||
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) {
|
||||
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) {
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
@@ -1218,7 +1224,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = Authorization::skip(fn () => $dbForProject->getDocument('teams', $teamId));
|
||||
$team = $authorization->skip(fn () => $dbForProject->getDocument('teams', $teamId));
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
@@ -1254,11 +1260,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
->setAttribute('confirm', true)
|
||||
;
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true)));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true)));
|
||||
|
||||
// Create session for the user if not logged in
|
||||
if (!$hasSession) {
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
$authorization->addRole(Role::user($user->getId())->toString());
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
@@ -1286,7 +1292,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
|
||||
$session = $dbForProject->createDocument('sessions', $session);
|
||||
|
||||
Authorization::setRole(Role::user($userId)->toString());
|
||||
$authorization->addRole(Role::user($userId)->toString());
|
||||
|
||||
$encoded = $store
|
||||
->setProperty('id', $user->getId())
|
||||
@@ -1324,7 +1330,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
$authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -1368,8 +1374,9 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Authorization $authorization, Event $queueForEvents) {
|
||||
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
|
||||
@@ -1427,7 +1434,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
if ($membership->getAttribute('confirm')) { // Count only confirmed members
|
||||
Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0));
|
||||
$authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0));
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
|
||||
@@ -2678,8 +2678,8 @@ App::get('/v1/users/usage')
|
||||
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('register')
|
||||
->action(function (string $range, Response $response, Database $dbForProject) {
|
||||
->inject('authorization')
|
||||
->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) {
|
||||
|
||||
$periods = Config::getParam('usage', []);
|
||||
$stats = $usage = [];
|
||||
@@ -2689,7 +2689,7 @@ App::get('/v1/users/usage')
|
||||
METRIC_SESSIONS,
|
||||
];
|
||||
|
||||
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
$authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
foreach ($metrics as $count => $metric) {
|
||||
$result = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
|
||||
+31
-29
@@ -76,7 +76,7 @@ use Utopia\VCS\Exception\RepositoryNotFound;
|
||||
|
||||
use function Swoole\Coroutine\batch;
|
||||
|
||||
$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, array $platform) {
|
||||
$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Authorization $authorization, Build $queueForBuilds, callable $getProjectDB, Request $request, array $platform) {
|
||||
$errors = [];
|
||||
foreach ($repositories as $repository) {
|
||||
try {
|
||||
@@ -87,12 +87,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
}
|
||||
|
||||
$projectId = $repository->getAttribute('projectId');
|
||||
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
$dbForProject = $getProjectDB($project);
|
||||
|
||||
$resourceCollection = $resourceType === "function" ? 'functions' : 'sites';
|
||||
$resourceId = $repository->getAttribute('resourceId');
|
||||
$resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
|
||||
$resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
|
||||
$resourceInternalId = $resource->getSequence();
|
||||
|
||||
$deploymentId = ID::unique();
|
||||
@@ -141,7 +141,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$latestCommentId = '';
|
||||
|
||||
if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) {
|
||||
$latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [
|
||||
$latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::equal('providerPullRequestId', [$providerPullRequestId]),
|
||||
Query::orderDesc('$createdAt'),
|
||||
@@ -180,7 +180,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
|
||||
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
|
||||
} finally {
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
$authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -191,7 +191,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
if (!empty($latestCommentId)) {
|
||||
$teamId = $project->getAttribute('teamId', '');
|
||||
|
||||
$latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([
|
||||
$latestComment = $authorization->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$permissions' => [
|
||||
Permission::read(Role::team(ID::custom($teamId))),
|
||||
@@ -212,7 +212,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
}
|
||||
}
|
||||
} elseif (!empty($providerBranch)) {
|
||||
$latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [
|
||||
$latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::equal('providerBranch', [$providerBranch]),
|
||||
Query::orderDesc('$createdAt'),
|
||||
@@ -251,7 +251,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
|
||||
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
|
||||
} finally {
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
$authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$commands[] = $resource->getAttribute('commands', '');
|
||||
}
|
||||
|
||||
$deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([
|
||||
$deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([
|
||||
'$id' => $deploymentId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
@@ -334,7 +334,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
->setAttribute('latestDeploymentInternalId', $deployment->getSequence())
|
||||
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource));
|
||||
|
||||
if ($resource->getCollection() === 'sites') {
|
||||
$projectId = $project->getId();
|
||||
@@ -344,7 +344,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
$ruleId = md5($domain);
|
||||
$previewRuleId = $ruleId;
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -377,7 +377,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -408,7 +408,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -460,7 +460,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
if ($lockAcquired) {
|
||||
// Wrap in try/finally to ensure lock file gets deleted
|
||||
try {
|
||||
$rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId));
|
||||
$rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId));
|
||||
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https';
|
||||
$previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : '';
|
||||
@@ -472,7 +472,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
$github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment());
|
||||
}
|
||||
} finally {
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
$authorization->skip(fn () => $dbForPlatform->deleteDocument('vcsCommentLocks', $latestCommentId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1476,11 +1476,12 @@ App::post('/v1/vcs/github/events')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('authorization')
|
||||
->inject('getProjectDB')
|
||||
->inject('queueForBuilds')
|
||||
->inject('platform')
|
||||
->action(
|
||||
function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) {
|
||||
function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) {
|
||||
$payload = $request->getRawPayload();
|
||||
$signatureRemote = $request->getHeader('x-hub-signature-256', '');
|
||||
$signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', '');
|
||||
@@ -1516,14 +1517,14 @@ App::post('/v1/vcs/github/events')
|
||||
$github->initializeVariables($providerInstallationId, $privateKey, $githubAppId);
|
||||
|
||||
//find resourceId from relevant resources table
|
||||
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
|
||||
$repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::limit(100),
|
||||
]));
|
||||
|
||||
// create new deployment only on push (not committed by us) and not when branch is created or deleted
|
||||
if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) {
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform);
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform);
|
||||
}
|
||||
} elseif ($event == $github::EVENT_INSTALLATION) {
|
||||
if ($parsedPayload["action"] == "deleted") {
|
||||
@@ -1536,16 +1537,16 @@ App::post('/v1/vcs/github/events')
|
||||
]);
|
||||
|
||||
foreach ($installations as $installation) {
|
||||
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
|
||||
$repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [
|
||||
Query::equal('installationInternalId', [$installation->getSequence()]),
|
||||
Query::limit(1000)
|
||||
]));
|
||||
|
||||
foreach ($repositories as $repository) {
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId()));
|
||||
$authorization->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId()));
|
||||
}
|
||||
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId()));
|
||||
$authorization->skip(fn () => $dbForPlatform->deleteDocument('installations', $installation->getId()));
|
||||
}
|
||||
}
|
||||
} elseif ($event == $github::EVENT_PULL_REQUEST) {
|
||||
@@ -1574,12 +1575,12 @@ App::post('/v1/vcs/github/events')
|
||||
$providerCommitAuthor = $commitDetails["commitAuthor"] ?? '';
|
||||
$providerCommitMessage = $commitDetails["commitMessage"] ?? '';
|
||||
|
||||
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
|
||||
$repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::orderDesc('$createdAt')
|
||||
]));
|
||||
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform);
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform);
|
||||
} elseif ($parsedPayload["action"] == "closed") {
|
||||
// Allowed external contributions cleanup
|
||||
|
||||
@@ -1588,7 +1589,7 @@ App::post('/v1/vcs/github/events')
|
||||
$external = $parsedPayload["external"] ?? true;
|
||||
|
||||
if ($external) {
|
||||
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
|
||||
$repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::orderDesc('$createdAt')
|
||||
]));
|
||||
@@ -1599,7 +1600,7 @@ App::post('/v1/vcs/github/events')
|
||||
if (\in_array($providerPullRequestId, $providerPullRequestIds)) {
|
||||
$providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]);
|
||||
$repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds);
|
||||
$repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository));
|
||||
$repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1786,17 +1787,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForPlatform')
|
||||
->inject('authorization')
|
||||
->inject('getProjectDB')
|
||||
->inject('queueForBuilds')
|
||||
->inject('platform')
|
||||
->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) {
|
||||
->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds, array $platform) use ($createGitDeployments) {
|
||||
$installation = $dbForPlatform->getDocument('installations', $installationId);
|
||||
|
||||
if ($installation->isEmpty()) {
|
||||
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$repository = Authorization::skip(fn () => $dbForPlatform->findOne('repositories', [
|
||||
$repository = $authorization->skip(fn () => $dbForPlatform->findOne('repositories', [
|
||||
Query::equal('$id', [$repositoryId]),
|
||||
Query::equal('projectInternalId', [$project->getSequence()])
|
||||
]));
|
||||
@@ -1814,7 +1816,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor
|
||||
|
||||
// TODO: Delete from array when PR is closed
|
||||
|
||||
$repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository));
|
||||
$repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository));
|
||||
|
||||
$privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY');
|
||||
$githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID');
|
||||
@@ -1846,7 +1848,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor
|
||||
$providerCommitMessage = $pullRequestResponse['title'] ?? '';
|
||||
$providerCommitUrl = $pullRequestResponse['html_url'] ?? '';
|
||||
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $platform);
|
||||
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request, $platform);
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
+98
-91
@@ -59,7 +59,7 @@ Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey)
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey)
|
||||
{
|
||||
$host = $request->getHostname() ?? '';
|
||||
if (!empty($previewHostname)) {
|
||||
@@ -67,16 +67,16 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
$rule = Authorization::skip(function () use ($dbForPlatform, $host, $isMd5) {
|
||||
if ($isMd5) {
|
||||
return $dbForPlatform->getDocument('rules', md5($host));
|
||||
}
|
||||
|
||||
return $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$host]),
|
||||
]) ?? new Document();
|
||||
});
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host)));
|
||||
} else {
|
||||
$rule = $authorization->skip(
|
||||
fn () => $dbForPlatform->find('rules', [
|
||||
Query::equal('domain', [$host]),
|
||||
Query::limit(1)
|
||||
])
|
||||
)[0] ?? new Document();
|
||||
}
|
||||
|
||||
$errorView = __DIR__ . '/../views/general/error.phtml';
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https';
|
||||
@@ -111,7 +111,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
$projectId = $rule->getAttribute('projectId');
|
||||
$project = Authorization::skip(
|
||||
$project = $authorization->skip(
|
||||
fn () => $dbForPlatform->getDocument('projects', $projectId)
|
||||
);
|
||||
|
||||
@@ -119,7 +119,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$accessedAt = $project->getAttribute('accessedAt', 0);
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) {
|
||||
$project->setAttribute('accessedAt', DateTime::now());
|
||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project));
|
||||
$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +158,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
|
||||
/** @var Document $deployment */
|
||||
if (!empty($rule->getAttribute('deploymentId', ''))) {
|
||||
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $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
|
||||
@@ -172,15 +172,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
|
||||
// Document of site or function
|
||||
$resource = $resourceType === 'function' ?
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) :
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId));
|
||||
$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));
|
||||
$deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId));
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('resourceType', '') === 'functions') {
|
||||
@@ -199,8 +199,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
$resource = $type === 'function' ?
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) :
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', '')));
|
||||
$authorization->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) :
|
||||
$authorization->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', '')));
|
||||
|
||||
$isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual');
|
||||
|
||||
@@ -242,7 +242,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$userExists = false;
|
||||
$userId = $payload['userId'] ?? '';
|
||||
if (!empty($userId)) {
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
if (!$user->isEmpty() && $user->getAttribute('status', false)) {
|
||||
$userExists = true;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
$membershipExists = false;
|
||||
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
if (!$project->isEmpty() && isset($user)) {
|
||||
$teamId = $project->getAttribute('teamId', '');
|
||||
$membership = $user->find('teamId', $teamId, 'memberships');
|
||||
@@ -862,15 +862,16 @@ App::init()
|
||||
->inject('devKey')
|
||||
->inject('apiKey')
|
||||
->inject('cors')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
$hostname = $request->getHostname() ?? '';
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
// Only run Router when external domain
|
||||
if (!in_array($hostname, $platformHostnames) || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) {
|
||||
if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1033,7 +1034,8 @@ App::init()
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForCertificates')
|
||||
->inject('platform')
|
||||
->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform) {
|
||||
->inject('authorization')
|
||||
->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) {
|
||||
$hostname = $request->getHostname();
|
||||
$cache = Config::getParam('hostnames', []);
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
@@ -1061,64 +1063,64 @@ App::init()
|
||||
}
|
||||
|
||||
// 4. Check/create rule (requires DB access)
|
||||
Authorization::disable();
|
||||
try {
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
$document = $isMd5
|
||||
? $dbForPlatform->getDocument('rules', md5($domain->get()))
|
||||
: $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain->get()]),
|
||||
$authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) {
|
||||
try {
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
$document = $isMd5
|
||||
? $dbForPlatform->getDocument('rules', md5($domain->get()))
|
||||
: $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain->get()]),
|
||||
]);
|
||||
|
||||
if (!$document->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. Create new rule
|
||||
$owner = '';
|
||||
$fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
|
||||
$funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$siteDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
|
||||
if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) {
|
||||
$funcDomain = $fallback;
|
||||
}
|
||||
|
||||
if (
|
||||
(!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) ||
|
||||
(!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain))
|
||||
) {
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
$ruleId = $isMd5 ? md5($domain->get()) : ID::unique();
|
||||
$document = new Document([
|
||||
'$id' => $ruleId,
|
||||
'domain' => $domain->get(),
|
||||
'type' => 'api',
|
||||
'status' => 'verifying',
|
||||
'projectId' => $console->getId(),
|
||||
'projectInternalId' => $console->getSequence(),
|
||||
'search' => implode(' ', [$ruleId, $domain->get()]),
|
||||
'owner' => $owner,
|
||||
'region' => $console->getAttribute('region')
|
||||
]);
|
||||
|
||||
if (!$document->isEmpty()) {
|
||||
return;
|
||||
$dbForPlatform->createDocument('rules', $document);
|
||||
|
||||
Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...');
|
||||
$queueForCertificates
|
||||
->setDomain($document)
|
||||
->setSkipRenewCheck(true)
|
||||
->trigger();
|
||||
} catch (Duplicate $e) {
|
||||
Console::info('Certificate already exists');
|
||||
} finally {
|
||||
$cache[$domain->get()] = true;
|
||||
Config::setParam('hostnames', $cache);
|
||||
}
|
||||
|
||||
// 5. Create new rule
|
||||
$owner = '';
|
||||
$fallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
|
||||
$funcDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$siteDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
|
||||
if (!empty($fallback) && \str_ends_with($domain->get(), $fallback)) {
|
||||
$funcDomain = $fallback;
|
||||
}
|
||||
|
||||
if (
|
||||
(!empty($funcDomain) && \str_ends_with($domain->get(), $funcDomain)) ||
|
||||
(!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain))
|
||||
) {
|
||||
$owner = 'Appwrite';
|
||||
}
|
||||
|
||||
$ruleId = $isMd5 ? md5($domain->get()) : ID::unique();
|
||||
$document = new Document([
|
||||
'$id' => $ruleId,
|
||||
'domain' => $domain->get(),
|
||||
'type' => 'api',
|
||||
'status' => 'verifying',
|
||||
'projectId' => $console->getId(),
|
||||
'projectInternalId' => $console->getSequence(),
|
||||
'search' => implode(' ', [$ruleId, $domain->get()]),
|
||||
'owner' => $owner,
|
||||
'region' => $console->getAttribute('region')
|
||||
]);
|
||||
|
||||
$dbForPlatform->createDocument('rules', $document);
|
||||
|
||||
Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...');
|
||||
$queueForCertificates
|
||||
->setDomain($document)
|
||||
->setSkipRenewCheck(true)
|
||||
->trigger();
|
||||
} catch (Duplicate $e) {
|
||||
Console::info('Certificate already exists');
|
||||
} finally {
|
||||
$cache[$domain->get()] = true;
|
||||
Config::setParam('hostnames', $cache);
|
||||
Authorization::reset();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
App::options()
|
||||
@@ -1141,14 +1143,15 @@ App::options()
|
||||
->inject('devKey')
|
||||
->inject('apiKey')
|
||||
->inject('cors')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
// Only run Router when external domain
|
||||
if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1182,7 +1185,8 @@ App::error()
|
||||
->inject('log')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('devKey')
|
||||
->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) {
|
||||
->inject('authorization')
|
||||
->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Document $devKey, Authorization $authorization) {
|
||||
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
$route = $utopia->getRoute();
|
||||
$class = \get_class($error);
|
||||
@@ -1264,7 +1268,7 @@ App::error()
|
||||
* If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php
|
||||
*/
|
||||
if (!$publish && $project->getId() !== 'console') {
|
||||
if (!DBUser::isPrivileged(Authorization::getRoles())) {
|
||||
if (!DBUser::isPrivileged($authorization->getRoles())) {
|
||||
$fileSize = 0;
|
||||
$file = $request->getFiles('file');
|
||||
if (!empty($file)) {
|
||||
@@ -1326,7 +1330,7 @@ App::error()
|
||||
$log->addExtra('file', $error->getFile());
|
||||
$log->addExtra('line', $error->getLine());
|
||||
$log->addExtra('trace', $error->getTraceAsString());
|
||||
$log->addExtra('roles', Authorization::getRoles());
|
||||
$log->addExtra('roles', $authorization->getRoles());
|
||||
|
||||
try {
|
||||
/* add queries to log */
|
||||
@@ -1530,13 +1534,14 @@ App::get('/robots.txt')
|
||||
->inject('platform')
|
||||
->inject('previewHostname')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) {
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
$template = new View(__DIR__ . '/../views/general/robots.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1562,13 +1567,14 @@ App::get('/humans.txt')
|
||||
->inject('platform')
|
||||
->inject('previewHostname')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization) {
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
$template = new View(__DIR__ . '/../views/general/humans.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1652,7 +1658,8 @@ App::get('/v1/ping')
|
||||
->inject('project')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForEvents')
|
||||
->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) {
|
||||
->inject('authorization')
|
||||
->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents, Authorization $authorization) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND);
|
||||
}
|
||||
@@ -1664,7 +1671,7 @@ App::get('/v1/ping')
|
||||
->setAttribute('pingCount', $pingCount)
|
||||
->setAttribute('pingedAt', $pingedAt);
|
||||
|
||||
Authorization::skip(function () use ($dbForPlatform, $project) {
|
||||
$authorization->skip(function () use ($dbForPlatform, $project) {
|
||||
$dbForPlatform->updateDocument('projects', $project->getId(), $project);
|
||||
});
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Authorization\Input;
|
||||
use Utopia\Queue\Publisher;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter as Telemetry;
|
||||
@@ -233,7 +234,8 @@ App::init()
|
||||
->inject('mode')
|
||||
->inject('team')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) {
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
/**
|
||||
@@ -318,7 +320,7 @@ App::init()
|
||||
// Handle special app role case
|
||||
if ($apiKey->getRole() === User::ROLE_APPS) {
|
||||
// Disable authorization checks for API keys
|
||||
Authorization::setDefaultStatus(false);
|
||||
$authorization->setDefaultStatus(false);
|
||||
|
||||
$user = new User([
|
||||
'$id' => '',
|
||||
@@ -392,14 +394,14 @@ App::init()
|
||||
$scopes = \array_merge($scopes, $roles[$role]['scopes']);
|
||||
}
|
||||
|
||||
Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
$authorization->setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
}
|
||||
|
||||
$scopes = \array_unique($scopes);
|
||||
|
||||
Authorization::setRole($role);
|
||||
foreach ($user->getRoles() as $authRole) {
|
||||
Authorization::setRole($authRole);
|
||||
$authorization->addRole($role);
|
||||
foreach ($user->getRoles($authorization) as $authRole) {
|
||||
$authorization->addRole($authRole);
|
||||
}
|
||||
|
||||
// Step 6: Update project and user last activity
|
||||
@@ -407,7 +409,7 @@ App::init()
|
||||
$accessedAt = $project->getAttribute('accessedAt', 0);
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) {
|
||||
$project->setAttribute('accessedAt', DateTime::now());
|
||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project));
|
||||
$authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +444,7 @@ App::init()
|
||||
if (
|
||||
array_key_exists($namespace, $project->getAttribute('services', []))
|
||||
&& !$project->getAttribute('services', [])[$namespace]
|
||||
&& !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles()))
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new Exception(Exception::GENERAL_SERVICE_DISABLED);
|
||||
}
|
||||
@@ -509,14 +511,15 @@ App::init()
|
||||
->inject('devKey')
|
||||
->inject('telemetry')
|
||||
->inject('platform')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Publisher $publisherFunctions, Publisher $publisherWebhooks, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Mail $queueForMails, Migration $queueForMigrations, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
if (
|
||||
array_key_exists('rest', $project->getAttribute('apis', []))
|
||||
&& !$project->getAttribute('apis', [])['rest']
|
||||
&& !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles()))
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
@@ -546,7 +549,7 @@ App::init()
|
||||
|
||||
$closestLimit = null;
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
|
||||
@@ -657,10 +660,10 @@ App::init()
|
||||
if ($useCache) {
|
||||
$route = $utopia->match($request);
|
||||
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged(Authorization::getRoles());
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$key = $request->cacheIdentifier();
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$cache = new Cache(
|
||||
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId())
|
||||
);
|
||||
@@ -677,10 +680,10 @@ App::init()
|
||||
|
||||
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {
|
||||
$bucketId = $parts[1] ?? null;
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
@@ -691,8 +694,7 @@ App::init()
|
||||
}
|
||||
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
$valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
@@ -703,7 +705,7 @@ App::init()
|
||||
if ($fileSecurity && !$valid && !$isToken) {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
|
||||
} else {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
$file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
}
|
||||
|
||||
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) {
|
||||
@@ -714,11 +716,11 @@ App::init()
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
//Do not update transformedAt if it's a console user
|
||||
if (!User::isPrivileged(Authorization::getRoles())) {
|
||||
if (!User::isPrivileged($authorization->getRoles())) {
|
||||
$transformedAt = $file->getAttribute('transformedAt', '');
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) {
|
||||
$file->setAttribute('transformedAt', DateTime::now());
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -814,8 +816,9 @@ App::shutdown()
|
||||
->inject('queueForWebhooks')
|
||||
->inject('queueForRealtime')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('timelimit')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, callable $timelimit) use ($parseLabel) {
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, Authorization $authorization, callable $timelimit) use ($parseLabel) {
|
||||
|
||||
$responsePayload = $response->getPayload();
|
||||
|
||||
@@ -976,11 +979,11 @@ App::shutdown()
|
||||
|
||||
$key = $request->cacheIdentifier();
|
||||
$signature = md5($data['payload']);
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$accessedAt = $cacheLog->getAttribute('accessedAt', 0);
|
||||
$now = DateTime::now();
|
||||
if ($cacheLog->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([
|
||||
$authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([
|
||||
'$id' => $key,
|
||||
'resource' => $resource,
|
||||
'resourceType' => $resourceType,
|
||||
@@ -990,7 +993,7 @@ App::shutdown()
|
||||
])));
|
||||
} elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) {
|
||||
$cacheLog->setAttribute('accessedAt', $now);
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog));
|
||||
// Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load()
|
||||
$cache->save($key, $data['payload']);
|
||||
}
|
||||
@@ -1002,7 +1005,7 @@ App::shutdown()
|
||||
}
|
||||
|
||||
if ($project->getId() !== 'console') {
|
||||
if (!User::isPrivileged(Authorization::getRoles())) {
|
||||
if (!User::isPrivileged($authorization->getRoles())) {
|
||||
$fileSize = 0;
|
||||
$file = $request->getFiles('file');
|
||||
if (!empty($file)) {
|
||||
|
||||
@@ -36,7 +36,8 @@ App::init()
|
||||
->inject('request')
|
||||
->inject('project')
|
||||
->inject('geodb')
|
||||
->action(function (App $utopia, Request $request, Document $project, Reader $geodb) {
|
||||
->inject('authorization')
|
||||
->action(function (App $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) {
|
||||
$denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
|
||||
if (!empty($denylist && $project->getId() === 'console')) {
|
||||
$countries = explode(',', $denylist);
|
||||
@@ -49,8 +50,8 @@ App::init()
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAppUser = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
|
||||
if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs
|
||||
return;
|
||||
|
||||
+17
-11
@@ -27,7 +27,6 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Logger\Log\User;
|
||||
use Utopia\Pools\Group;
|
||||
@@ -261,7 +260,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
||||
createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools);
|
||||
|
||||
// create appwrite database, `dbForPlatform` is a direct access call.
|
||||
createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) {
|
||||
createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections, $app) {
|
||||
$authorization = $app->getResource('authorization');
|
||||
|
||||
if ($dbForPlatform->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) {
|
||||
$adapter = new AdapterDatabase($dbForPlatform);
|
||||
$audit = new Audit($adapter);
|
||||
@@ -321,9 +322,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
||||
$dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes);
|
||||
}
|
||||
|
||||
if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) {
|
||||
if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) {
|
||||
Console::info(" └── Creating screenshots bucket...");
|
||||
Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([
|
||||
$authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([
|
||||
'$id' => ID::custom('screenshots'),
|
||||
'$collection' => ID::custom('buckets'),
|
||||
'name' => 'Screenshots',
|
||||
@@ -338,7 +339,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
||||
'search' => 'buckets Screenshots',
|
||||
])));
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots'));
|
||||
$bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots'));
|
||||
|
||||
Console::info(" └── Creating files collection for screenshots bucket...");
|
||||
$files = $collections['buckets']['files'] ?? [];
|
||||
@@ -366,7 +367,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
||||
'orders' => $index['orders'],
|
||||
]), $files['indexes']);
|
||||
|
||||
Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes));
|
||||
$authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -458,8 +459,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
|
||||
App::setResource('pools', fn () => $pools);
|
||||
|
||||
try {
|
||||
Authorization::cleanRoles();
|
||||
Authorization::setRole(Role::any()->toString());
|
||||
$authorization = $app->getResource('authorization');
|
||||
|
||||
$request->setAuthorization($authorization);
|
||||
$response->setAuthorization($authorization);
|
||||
$authorization->cleanRoles();
|
||||
$authorization->addRole(Role::any()->toString());
|
||||
|
||||
$app->run($request, $response);
|
||||
} catch (\Throwable $th) {
|
||||
@@ -501,7 +506,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
|
||||
$log->addExtra('file', $th->getFile());
|
||||
$log->addExtra('line', $th->getLine());
|
||||
$log->addExtra('trace', $th->getTraceAsString());
|
||||
$log->addExtra('roles', Authorization::getRoles());
|
||||
$log->addExtra('roles', isset($authorization) ? $authorization->getRoles() : []);
|
||||
|
||||
$sdk = $route->getLabel("sdk", false);
|
||||
|
||||
@@ -560,7 +565,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
/** @var Utopia\Database\Database $dbForPlatform */
|
||||
$dbForPlatform = $app->getResource('dbForPlatform');
|
||||
|
||||
Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate) {
|
||||
Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) {
|
||||
try {
|
||||
$time = DateTime::now();
|
||||
$limit = 1000;
|
||||
@@ -577,7 +582,8 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
}
|
||||
$results = [];
|
||||
try {
|
||||
$results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries));
|
||||
$authorization = $app->getResource('authorization');
|
||||
$results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries));
|
||||
} catch (Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
}
|
||||
|
||||
@@ -161,6 +161,9 @@ const ACTIVITY_TYPE_GUEST = 'guest';
|
||||
const MFA_RECENT_DURATION = 1800; // 30 mins
|
||||
|
||||
|
||||
// Database name
|
||||
const APP_DATABASE = 'appwrite';
|
||||
|
||||
// Database Reconnect
|
||||
const DATABASE_RECONNECT_SLEEP = 2;
|
||||
const DATABASE_RECONNECT_MAX_ATTEMPTS = 10;
|
||||
|
||||
@@ -4,7 +4,6 @@ use Appwrite\OpenSSL\OpenSSL;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\System\System;
|
||||
|
||||
Database::addFilter(
|
||||
@@ -70,11 +69,11 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
$attributes = $database->find('attributes', [
|
||||
$attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [
|
||||
Query::equal('collectionInternalId', [$document->getSequence()]),
|
||||
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
|
||||
Query::limit($database->getLimitForAttributes()),
|
||||
]);
|
||||
]));
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$attributeType = $attribute->getAttribute('type');
|
||||
@@ -105,12 +104,12 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('indexes', [
|
||||
Query::equal('collectionInternalId', [$document->getSequence()]),
|
||||
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
|
||||
Query::limit($database->getLimitForIndexes()),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -120,11 +119,11 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('platforms', [
|
||||
Query::equal('projectInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -134,12 +133,12 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('keys', [
|
||||
Query::equal('resourceType', ['projects']),
|
||||
Query::equal('resourceInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -149,11 +148,11 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('devKeys', [
|
||||
Query::equal('projectInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -163,11 +162,11 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('webhooks', [
|
||||
Query::equal('projectInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -177,7 +176,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database->find('sessions', [
|
||||
return $database->getAuthorization()->skip(fn () => $database->find('sessions', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]));
|
||||
@@ -190,7 +189,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('tokens', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
@@ -204,7 +203,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('challenges', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
@@ -218,7 +217,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('authenticators', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
@@ -232,7 +231,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('memberships', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
@@ -252,14 +251,14 @@ Database::addFilter(
|
||||
default => ['function', 'site']
|
||||
};
|
||||
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('variables', [
|
||||
Query::equal('resourceInternalId', [$document->getSequence()]),
|
||||
Query::equal('resourceType', $resourceType),
|
||||
Query::orderAsc('resourceType'),
|
||||
Query::orderAsc(),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -295,11 +294,11 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('variables', [
|
||||
Query::equal('resourceType', ['project']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]);
|
||||
]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -332,7 +331,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return Authorization::skip(fn () => $database
|
||||
return $database->getAuthorization()->skip(fn () => $database
|
||||
->find('targets', [
|
||||
Query::equal('userInternalId', [$document->getSequence()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
@@ -346,7 +345,7 @@ Database::addFilter(
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
$targetIds = Authorization::skip(fn () => \array_map(
|
||||
$targetIds = $database->getAuthorization()->skip(fn () => \array_map(
|
||||
fn ($document) => $document->getAttribute('targetInternalId'),
|
||||
$database->find('subscribers', [
|
||||
Query::equal('topicInternalId', [$document->getSequence()]),
|
||||
|
||||
@@ -324,6 +324,12 @@ $register->set('pools', function () {
|
||||
Config::setParam('pools-' . $key, $config);
|
||||
}
|
||||
|
||||
$reconnectAttempts = (int) System::getEnv('_APP_CONNECTIONS_RECONNECT_ATTEMPTS', 5);
|
||||
$reconnectSleep = (int) System::getEnv('_APP_CONNECTIONS_RECONNECT_SLEEP', 2);
|
||||
|
||||
$group->setReconnectAttempts($reconnectAttempts);
|
||||
$group->setReconnectSleep($reconnectSleep);
|
||||
|
||||
return $group;
|
||||
});
|
||||
|
||||
|
||||
+62
-48
@@ -230,7 +230,7 @@ App::setResource('allowedSchemes', function (Document $project) {
|
||||
/**
|
||||
* Rule associated with a request origin.
|
||||
*/
|
||||
App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project) {
|
||||
App::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) {
|
||||
$domain = \parse_url($request->getOrigin(), PHP_URL_HOST);
|
||||
if (empty($domain)) {
|
||||
return new Document();
|
||||
@@ -238,7 +238,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do
|
||||
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
$rule = Authorization::skip(function () use ($dbForPlatform, $domain, $isMd5) {
|
||||
$rule = $authorization->skip(function () use ($dbForPlatform, $domain, $isMd5) {
|
||||
if ($isMd5) {
|
||||
return $dbForPlatform->getDocument('rules', md5($domain));
|
||||
}
|
||||
@@ -253,7 +253,7 @@ App::setResource('rule', function (Request $request, Database $dbForPlatform, Do
|
||||
}
|
||||
|
||||
return $rule;
|
||||
}, ['request', 'dbForPlatform', 'project']);
|
||||
}, ['request', 'dbForPlatform', 'project', 'authorization']);
|
||||
|
||||
/**
|
||||
* CORS service
|
||||
@@ -321,7 +321,7 @@ App::setResource('redirectValidator', function (Document $devKey, array $allowed
|
||||
return new Redirect($allowedHostnames, $allowedSchemes);
|
||||
}, ['devKey', 'allowedHostnames', 'allowedSchemes']);
|
||||
|
||||
App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) {
|
||||
App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken, $authorization) {
|
||||
/**
|
||||
* Handles user authentication and session validation.
|
||||
*
|
||||
@@ -341,7 +341,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co
|
||||
* overwriting the previous value.
|
||||
*/
|
||||
|
||||
Authorization::setDefaultStatus(true);
|
||||
$authorization->setDefaultStatus(true);
|
||||
|
||||
$store->setKey('a_session_' . $project->getId());
|
||||
|
||||
@@ -408,7 +408,7 @@ App::setResource('user', function (string $mode, Document $project, Document $co
|
||||
}
|
||||
// if (APP_MODE_ADMIN === $mode) {
|
||||
// if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
|
||||
// Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
// $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
// } else {
|
||||
// $user = new Document([]);
|
||||
// }
|
||||
@@ -440,9 +440,9 @@ App::setResource('user', function (string $mode, Document $project, Document $co
|
||||
$dbForPlatform->setMetadata('user', $user->getId());
|
||||
|
||||
return $user;
|
||||
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']);
|
||||
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken', 'authorization']);
|
||||
|
||||
App::setResource('project', function ($dbForPlatform, $request, $console) {
|
||||
App::setResource('project', function ($dbForPlatform, $request, $console, $authorization) {
|
||||
/** @var Appwrite\Utopia\Request $request */
|
||||
/** @var Utopia\Database\Database $dbForPlatform */
|
||||
/** @var Utopia\Database\Document $console */
|
||||
@@ -453,10 +453,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) {
|
||||
return $console;
|
||||
}
|
||||
|
||||
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
|
||||
return $project;
|
||||
}, ['dbForPlatform', 'request', 'console']);
|
||||
}, ['dbForPlatform', 'request', 'console', 'authorization']);
|
||||
|
||||
App::setResource('session', function (User $user, Store $store, Token $proofForToken) {
|
||||
if ($user->isEmpty()) {
|
||||
@@ -479,10 +479,6 @@ App::setResource('session', function (User $user, Store $store, Token $proofForT
|
||||
return;
|
||||
}, ['user', 'store', 'proofForToken']);
|
||||
|
||||
App::setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
}, []);
|
||||
|
||||
App::setResource('store', function (): Store {
|
||||
return new Store();
|
||||
});
|
||||
@@ -513,7 +509,15 @@ App::setResource('proofForCode', function (): Code {
|
||||
return $code;
|
||||
});
|
||||
|
||||
App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) {
|
||||
App::setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
}, []);
|
||||
|
||||
App::setResource('authorization', function () {
|
||||
return new Authorization();
|
||||
}, []);
|
||||
|
||||
App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project, Authorization $authorization) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -529,6 +533,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId())
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
|
||||
@@ -550,13 +556,16 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
|
||||
}
|
||||
|
||||
return $database;
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'project']);
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']);
|
||||
|
||||
App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
|
||||
App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
|
||||
$adapter = new DatabasePool($pools->get('console'));
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setNamespace('_console')
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', 'console')
|
||||
@@ -566,12 +575,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
|
||||
$database->setDocumentType('users', User::class);
|
||||
|
||||
return $database;
|
||||
}, ['pools', 'cache']);
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
|
||||
App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) {
|
||||
$databases = [];
|
||||
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) {
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -583,13 +592,16 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
|
||||
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
|
||||
}
|
||||
|
||||
$configure = (function (Database $database) use ($project, $dsn) {
|
||||
$configure = (function (Database $database) use ($project, $dsn, $authorization) {
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId())
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
|
||||
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
|
||||
$database->setDocumentType('users', User::class);
|
||||
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES)
|
||||
->setDocumentType('users', User::class)
|
||||
;
|
||||
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
@@ -619,12 +631,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache']);
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'authorization']);
|
||||
|
||||
App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$database = null;
|
||||
|
||||
return function (?Document $project = null) use ($pools, $cache, &$database) {
|
||||
return function (?Document $project = null) use ($pools, $cache, $authorization, &$database) {
|
||||
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$database->setTenant((int) $project->getSequence());
|
||||
return $database;
|
||||
@@ -634,6 +646,8 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setSharedTables(true)
|
||||
->setNamespace('logsV1')
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
|
||||
@@ -646,7 +660,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'cache']);
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
App::setResource('audit', function ($dbForProject) {
|
||||
$adapter = new AdapterDatabase($dbForProject);
|
||||
@@ -845,7 +859,7 @@ App::setResource('promiseAdapter', function ($register) {
|
||||
return $register->get('promiseAdapter');
|
||||
}, ['register']);
|
||||
|
||||
App::setResource('schema', function ($utopia, $dbForProject) {
|
||||
App::setResource('schema', function ($utopia, $dbForProject, $authorization) {
|
||||
|
||||
$complexity = function (int $complexity, array $args) {
|
||||
$queries = Query::parseQueries($args['queries'] ?? []);
|
||||
@@ -855,8 +869,8 @@ App::setResource('schema', function ($utopia, $dbForProject) {
|
||||
return $complexity * $limit;
|
||||
};
|
||||
|
||||
$attributes = function (int $limit, int $offset) use ($dbForProject) {
|
||||
$attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [
|
||||
$attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) {
|
||||
$attrs = $authorization->skip(fn () => $dbForProject->find('attributes', [
|
||||
Query::limit($limit),
|
||||
Query::offset($offset),
|
||||
]));
|
||||
@@ -930,7 +944,7 @@ App::setResource('schema', function ($utopia, $dbForProject) {
|
||||
$urls,
|
||||
$params,
|
||||
);
|
||||
}, ['utopia', 'dbForProject']);
|
||||
}, ['utopia', 'dbForProject', 'authorization']);
|
||||
|
||||
App::setResource('gitHub', function (Cache $cache) {
|
||||
return new VcsGitHub($cache);
|
||||
@@ -958,7 +972,7 @@ App::setResource('smsRates', function () {
|
||||
return [];
|
||||
});
|
||||
|
||||
App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) {
|
||||
App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform, Authorization $authorization) {
|
||||
$devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', ''));
|
||||
|
||||
// Check if given key match project's development keys
|
||||
@@ -977,7 +991,7 @@ App::setResource('devKey', function (Request $request, Document $project, array
|
||||
$accessedAt = $key->getAttribute('accessedAt', 0);
|
||||
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
|
||||
$key->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
|
||||
@@ -994,15 +1008,15 @@ App::setResource('devKey', function (Request $request, Document $project, array
|
||||
|
||||
/** Update access time as well */
|
||||
$key->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
$key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$key = $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}, ['request', 'project', 'servers', 'dbForPlatform']);
|
||||
}, ['request', 'project', 'servers', 'dbForPlatform', 'authorization']);
|
||||
|
||||
App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) {
|
||||
App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request, Authorization $authorization) {
|
||||
$teamInternalId = '';
|
||||
if ($project->getId() !== 'console') {
|
||||
$teamInternalId = $project->getAttribute('teamInternalId', '');
|
||||
@@ -1012,7 +1026,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A
|
||||
if (str_starts_with($path, '/v1/projects/:projectId')) {
|
||||
$uri = $request->getURI();
|
||||
$pid = explode('/', $uri)[3];
|
||||
$p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid));
|
||||
$p = $authorization->skip(fn () => $dbForPlatform->getDocument('projects', $pid));
|
||||
$teamInternalId = $p->getAttribute('teamInternalId', '');
|
||||
} elseif ($path === '/v1/projects') {
|
||||
$teamId = $request->getParam('teamId', '');
|
||||
@@ -1021,7 +1035,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId));
|
||||
$team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId));
|
||||
return $team;
|
||||
}
|
||||
}
|
||||
@@ -1030,14 +1044,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) {
|
||||
$team = $authorization->skip(function () use ($dbForPlatform, $teamInternalId) {
|
||||
return $dbForPlatform->findOne('teams', [
|
||||
Query::equal('$sequence', [$teamInternalId]),
|
||||
]);
|
||||
});
|
||||
|
||||
return $team;
|
||||
}, ['project', 'dbForPlatform', 'utopia', 'request']);
|
||||
}, ['project', 'dbForPlatform', 'utopia', 'request', 'authorization']);
|
||||
|
||||
App::setResource(
|
||||
'isResourceBlocked',
|
||||
@@ -1075,7 +1089,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key
|
||||
|
||||
App::setResource('executor', fn () => new Executor());
|
||||
|
||||
App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
App::setResource('resourceToken', function ($project, $dbForProject, $request, Authorization $authorization) {
|
||||
$tokenJWT = $request->getParam('token');
|
||||
|
||||
if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication
|
||||
@@ -1093,7 +1107,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId));
|
||||
$token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId));
|
||||
|
||||
if ($token->isEmpty()) {
|
||||
return new Document([]);
|
||||
@@ -1111,7 +1125,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
}
|
||||
|
||||
return match ($token->getAttribute('resourceType')) {
|
||||
TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) {
|
||||
TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject, $authorization) {
|
||||
$sequences = explode(':', $token->getAttribute('resourceInternalId'));
|
||||
$ids = explode(':', $token->getAttribute('resourceId'));
|
||||
|
||||
@@ -1122,7 +1136,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
$accessedAt = $token->getAttribute('accessedAt', 0);
|
||||
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) {
|
||||
$token->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token));
|
||||
}
|
||||
|
||||
return new Document([
|
||||
@@ -1137,8 +1151,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
};
|
||||
}
|
||||
return new Document([]);
|
||||
}, ['project', 'dbForProject', 'request']);
|
||||
}, ['project', 'dbForProject', 'request', 'authorization']);
|
||||
|
||||
App::setResource('transactionState', function (Database $dbForProject) {
|
||||
return new TransactionState($dbForProject);
|
||||
}, ['dbForProject']);
|
||||
App::setResource('transactionState', function (Database $dbForProject, Authorization $authorization) {
|
||||
return new TransactionState($dbForProject, $authorization);
|
||||
}, ['dbForProject', 'authorization']);
|
||||
|
||||
+32
-11
@@ -32,7 +32,6 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Pools\Group;
|
||||
@@ -67,6 +66,7 @@ if (!function_exists('getConsoleDB')) {
|
||||
$adapter = new DatabasePool($pools->get('console'));
|
||||
$database = new Database($adapter, getCache());
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setNamespace('_console')
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', '_console');
|
||||
@@ -123,6 +123,7 @@ if (!function_exists('getProjectDB')) {
|
||||
}
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId());
|
||||
|
||||
@@ -309,7 +310,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
|
||||
'value' => '{}'
|
||||
]);
|
||||
|
||||
$statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document));
|
||||
$statsDocument = $database->getAuthorization()->skip(fn () => $database->createDocument('realtime', $document));
|
||||
break;
|
||||
} catch (Throwable) {
|
||||
Console::warning("Collection not ready. Retrying connection ({$attempts})...");
|
||||
@@ -339,7 +340,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
|
||||
->setAttribute('timestamp', DateTime::now())
|
||||
->setAttribute('value', json_encode($payload));
|
||||
|
||||
Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
|
||||
$database->getAuthorization()->skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
|
||||
} catch (Throwable $th) {
|
||||
$logError($th, "updateWorkerDocument");
|
||||
}
|
||||
@@ -370,7 +371,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
||||
|
||||
$payload = [];
|
||||
|
||||
$list = Authorization::skip(fn () => $database->find('realtime', [
|
||||
$list = $database->getAuthorization()->skip(fn () => $database->find('realtime', [
|
||||
Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)),
|
||||
]));
|
||||
|
||||
@@ -464,13 +465,13 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
||||
if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) {
|
||||
$connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId]));
|
||||
$consoleDatabase = getConsoleDB();
|
||||
$project = Authorization::skip(fn () => $consoleDatabase->getDocument('projects', $projectId));
|
||||
$project = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId));
|
||||
$database = getProjectDB($project);
|
||||
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $user */
|
||||
$user = $database->getDocument('users', $userId);
|
||||
|
||||
$roles = $user->getRoles();
|
||||
$roles = $user->getRoles($database->getAuthorization());
|
||||
$channels = $realtime->connections[$connection]['channels'];
|
||||
|
||||
$realtime->unsubscribe($connection);
|
||||
@@ -526,6 +527,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
try {
|
||||
/** @var Document $project */
|
||||
$project = $app->getResource('project');
|
||||
$authorization = $app->getResource('authorization');
|
||||
|
||||
/*
|
||||
* Project Check
|
||||
@@ -537,7 +539,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
if (
|
||||
array_key_exists('realtime', $project->getAttribute('apis', []))
|
||||
&& !$project->getAttribute('apis', [])['realtime']
|
||||
&& !(User::isPrivileged(Authorization::getRoles()) || User::isApp(Authorization::getRoles()))
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
@@ -573,7 +575,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription());
|
||||
}
|
||||
|
||||
$roles = $user->getRoles();
|
||||
$roles = $user->getRoles($authorization);
|
||||
|
||||
$channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId());
|
||||
|
||||
@@ -586,6 +588,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
|
||||
$realtime->subscribe($project->getId(), $connection, $roles, $channels);
|
||||
|
||||
$realtime->connections[$connection]['authorization'] = $authorization;
|
||||
|
||||
$user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_ACCOUNT);
|
||||
|
||||
$server->send([$connection], json_encode([
|
||||
@@ -614,6 +618,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
$code = 500;
|
||||
}
|
||||
|
||||
|
||||
$message = $th->getMessage();
|
||||
|
||||
// sanitize 0 && 5xx errors
|
||||
@@ -643,12 +648,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
|
||||
try {
|
||||
$response = new Response(new SwooleResponse());
|
||||
$projectId = $realtime->connections[$connection]['projectId'];
|
||||
$projectId = $realtime->connections[$connection]['projectId'] ?? null;
|
||||
|
||||
// Get authorization from connection (stored during onOpen)
|
||||
$authorization = $realtime->connections[$connection]['authorization'] ?? null;
|
||||
|
||||
$database = getConsoleDB();
|
||||
$database->setAuthorization($authorization);
|
||||
|
||||
if ($projectId !== 'console') {
|
||||
$project = Authorization::skip(fn () => $database->getDocument('projects', $projectId));
|
||||
$project = $authorization->skip(fn () => $database->getDocument('projects', $projectId));
|
||||
|
||||
$database = getProjectDB($project);
|
||||
$database->setAuthorization($authorization);
|
||||
} else {
|
||||
$project = null;
|
||||
}
|
||||
@@ -712,10 +724,19 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.');
|
||||
}
|
||||
|
||||
$roles = $user->getRoles();
|
||||
$roles = $user->getRoles($database->getAuthorization());
|
||||
$channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId());
|
||||
|
||||
// Preserve authorization before subscribe overwrites the connection array
|
||||
$authorization = $realtime->connections[$connection]['authorization'] ?? null;
|
||||
|
||||
$realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels);
|
||||
|
||||
// Restore authorization after subscribe
|
||||
if ($authorization !== null) {
|
||||
$realtime->connections[$connection]['authorization'] = $authorization;
|
||||
}
|
||||
|
||||
$user = $response->output($user, Response::MODEL_ACCOUNT);
|
||||
$server->send([$connection], json_encode([
|
||||
'type' => 'response',
|
||||
|
||||
+39
-18
@@ -49,19 +49,31 @@ use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter as Telemetry;
|
||||
use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
||||
|
||||
Authorization::disable();
|
||||
Runtime::enableCoroutine();
|
||||
|
||||
Server::setResource('register', fn () => $register);
|
||||
|
||||
Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) {
|
||||
Server::setResource('authorization', function () {
|
||||
$authorization = new Authorization();
|
||||
$authorization->disable();
|
||||
return $authorization;
|
||||
}, []);
|
||||
|
||||
Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, Authorization $authorization) {
|
||||
$pools = $register->get('pools');
|
||||
$adapter = new DatabasePool($pools->get('console'));
|
||||
$dbForPlatform = new Database($adapter, $cache);
|
||||
$dbForPlatform->setNamespace('_console');
|
||||
$dbForPlatform->setDocumentType('users', User::class);
|
||||
|
||||
$dbForPlatform
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setNamespace('_console')
|
||||
->setDocumentType('users', User::class)
|
||||
;
|
||||
|
||||
|
||||
return $dbForPlatform;
|
||||
}, ['cache', 'register']);
|
||||
}, ['cache', 'register', 'authorization']);
|
||||
|
||||
Server::setResource('project', function (Message $message, Database $dbForPlatform) {
|
||||
$payload = $message->getPayload() ?? [];
|
||||
@@ -74,7 +86,7 @@ Server::setResource('project', function (Message $message, Database $dbForPlatfo
|
||||
return $dbForPlatform->getDocument('projects', $project->getId());
|
||||
}, ['message', 'dbForPlatform']);
|
||||
|
||||
Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) {
|
||||
Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform, Authorization $authorization) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -106,15 +118,18 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
|
||||
->setNamespace('_' . $project->getSequence());
|
||||
}
|
||||
|
||||
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
|
||||
|
||||
return $database;
|
||||
}, ['cache', 'register', 'message', 'project', 'dbForPlatform']);
|
||||
}, ['cache', 'register', 'message', 'project', 'dbForPlatform', 'authorization']);
|
||||
|
||||
Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
|
||||
Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, Authorization $authorization) {
|
||||
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
|
||||
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database {
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases): Database {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -128,7 +143,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf
|
||||
|
||||
if (isset($databases[$dsn->getHost()])) {
|
||||
$database = $databases[$dsn->getHost()];
|
||||
|
||||
$database->setAuthorization($authorization);
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
if (\in_array($dsn->getHost(), $sharedTables)) {
|
||||
@@ -165,15 +180,18 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf
|
||||
->setNamespace('_' . $project->getSequence());
|
||||
}
|
||||
|
||||
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache']);
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'authorization']);
|
||||
|
||||
Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
Server::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$database = null;
|
||||
return function (?Document $project = null) use ($pools, $cache, $database) {
|
||||
return function (?Document $project = null) use ($pools, $cache, $database, $authorization) {
|
||||
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$database->setTenant((int)$project->getSequence());
|
||||
return $database;
|
||||
@@ -183,6 +201,8 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setSharedTables(true)
|
||||
->setNamespace('logsV1')
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER)
|
||||
@@ -195,7 +215,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'cache']);
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
Server::setResource('abuseRetention', function () {
|
||||
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day
|
||||
@@ -514,7 +534,8 @@ $worker
|
||||
->inject('log')
|
||||
->inject('pools')
|
||||
->inject('project')
|
||||
->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) {
|
||||
->inject('authorization')
|
||||
->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project, Authorization $authorization) use ($worker, $queueName) {
|
||||
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
|
||||
if ($logger) {
|
||||
@@ -530,7 +551,7 @@ $worker
|
||||
$log->addExtra('file', $error->getFile());
|
||||
$log->addExtra('line', $error->getLine());
|
||||
$log->addExtra('trace', $error->getTraceAsString());
|
||||
$log->addExtra('roles', Authorization::getRoles());
|
||||
$log->addExtra('roles', $authorization->getRoles());
|
||||
|
||||
$isProduction = System::getEnv('_APP_ENV', 'development') === 'production';
|
||||
$log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING);
|
||||
|
||||
+8
-8
@@ -45,18 +45,18 @@
|
||||
"ext-sockets": "*",
|
||||
"appwrite/php-runtimes": "0.19.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "1.*.*",
|
||||
"utopia-php/abuse": "1.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
"utopia-php/audit": "2.0.2-rc3",
|
||||
"utopia-php/audit": "2.*",
|
||||
"utopia-php/auth": "0.5.*",
|
||||
"utopia-php/cache": "0.13.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "1.*.*",
|
||||
"utopia-php/database": "3.*.*",
|
||||
"utopia-php/config": "1.*",
|
||||
"utopia-php/database": "4.*",
|
||||
"utopia-php/detector": "0.2.*",
|
||||
"utopia-php/domains": "0.9.*",
|
||||
"utopia-php/domains": "0.11.*",
|
||||
"utopia-php/emails": "0.6.*",
|
||||
"utopia-php/dns": "1.4.*",
|
||||
"utopia-php/dns": "1.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/fetch": "0.5.*",
|
||||
@@ -64,7 +64,7 @@
|
||||
"utopia-php/locale": "0.8.*",
|
||||
"utopia-php/logger": "0.6.*",
|
||||
"utopia-php/messaging": "0.20.*",
|
||||
"utopia-php/migration": "1.3.*",
|
||||
"utopia-php/migration": "1.*",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.7.*",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
@@ -72,7 +72,7 @@
|
||||
"utopia-php/queue": "0.15.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
"utopia-php/storage": "0.18.*",
|
||||
"utopia-php/swoole": "0.8.*",
|
||||
"utopia-php/swoole": "1.*",
|
||||
"utopia-php/system": "0.9.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/vcs": "0.13.*",
|
||||
|
||||
Generated
+128
-87
@@ -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": "ff3172688b600aa3c560131c9d9c5588",
|
||||
"content-hash": "33da844fdf5648d1d1a027dfb6ae42bc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -756,16 +756,16 @@
|
||||
},
|
||||
{
|
||||
"name": "google/protobuf",
|
||||
"version": "v4.33.2",
|
||||
"version": "v4.33.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/protocolbuffers/protobuf-php.git",
|
||||
"reference": "fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318"
|
||||
"reference": "22d28025cda0d223a2e48c2e16c5284ecc9f5402"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318",
|
||||
"reference": "fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/22d28025cda0d223a2e48c2e16c5284ecc9f5402",
|
||||
"reference": "22d28025cda0d223a2e48c2e16c5284ecc9f5402",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -794,9 +794,9 @@
|
||||
"proto"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.2"
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.4"
|
||||
},
|
||||
"time": "2025-12-05T22:12:22+00:00"
|
||||
"time": "2026-01-12T17:58:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
@@ -3455,25 +3455,25 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/abuse",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/abuse.git",
|
||||
"reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2"
|
||||
"reference": "15cd5dbefa4453e8a2d90649a7078e242966ac3f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/3339d057c6bb1fa3e5ac5b2598923f6938425ec2",
|
||||
"reference": "3339d057c6bb1fa3e5ac5b2598923f6938425ec2",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/15cd5dbefa4453e8a2d90649a7078e242966ac3f",
|
||||
"reference": "15cd5dbefa4453e8a2d90649a7078e242966ac3f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"appwrite/appwrite": "19.*.*",
|
||||
"appwrite/appwrite": "19.*",
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*",
|
||||
"ext-redis": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "3.*.*"
|
||||
"utopia-php/database": "4.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
@@ -3501,9 +3501,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/abuse/issues",
|
||||
"source": "https://github.com/utopia-php/abuse/tree/1.2.0"
|
||||
"source": "https://github.com/utopia-php/abuse/tree/1.2.1"
|
||||
},
|
||||
"time": "2026-01-05T21:29:10+00:00"
|
||||
"time": "2026-01-15T02:09:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/analytics",
|
||||
@@ -3553,23 +3553,23 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/audit",
|
||||
"version": "2.0.2-rc3",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/audit.git",
|
||||
"reference": "f60a298b516300f56a328403b334b7d62a96e7e7"
|
||||
"reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7",
|
||||
"reference": "f60a298b516300f56a328403b334b7d62a96e7e7",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/1301ab2607667b9f86456f86895f3e26f8c0c9a7",
|
||||
"reference": "1301ab2607667b9f86456f86895f3e26f8c0c9a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "3.*",
|
||||
"utopia-php/database": "4.*",
|
||||
"utopia-php/fetch": "0.5.*",
|
||||
"utopia-php/validators": "0.1.*"
|
||||
"utopia-php/validators": "0.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
@@ -3596,9 +3596,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/audit/issues",
|
||||
"source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3"
|
||||
"source": "https://github.com/utopia-php/audit/tree/2.0.4"
|
||||
},
|
||||
"time": "2026-01-06T15:32:52+00:00"
|
||||
"time": "2026-01-14T07:22:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/auth",
|
||||
@@ -3899,16 +3899,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "3.6.1",
|
||||
"version": "4.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7"
|
||||
"reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/c8c1b2f5770245dd4006e2680681e3efbe8b1fa7",
|
||||
"reference": "c8c1b2f5770245dd4006e2680681e3efbe8b1fa7",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23",
|
||||
"reference": "8e6a033d4da09a2f2ac1f79fd85fcfa2da018d23",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3951,9 +3951,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/3.6.1"
|
||||
"source": "https://github.com/utopia-php/database/tree/4.5.2"
|
||||
},
|
||||
"time": "2025-12-16T09:55:41+00:00"
|
||||
"time": "2026-01-15T04:23:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
@@ -4002,22 +4002,22 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dns",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dns.git",
|
||||
"reference": "5daf8b683dad877491c4df84c6be24850b2f363b"
|
||||
"reference": "a1f490ba425b1a5128e7aaa24eff560900812d21"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/5daf8b683dad877491c4df84c6be24850b2f363b",
|
||||
"reference": "5daf8b683dad877491c4df84c6be24850b2f363b",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/a1f490ba425b1a5128e7aaa24eff560900812d21",
|
||||
"reference": "a1f490ba425b1a5128e7aaa24eff560900812d21",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3",
|
||||
"utopia-php/console": "0.0.*",
|
||||
"utopia-php/domains": "0.9.*",
|
||||
"utopia-php/domains": "0.11.*",
|
||||
"utopia-php/span": "1.0.*",
|
||||
"utopia-php/telemetry": "*",
|
||||
"utopia-php/validators": "0.*"
|
||||
},
|
||||
@@ -4053,22 +4053,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dns/issues",
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.4.1"
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.5.3"
|
||||
},
|
||||
"time": "2025-12-17T09:09:08+00:00"
|
||||
"time": "2026-01-13T11:39:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
"version": "0.9.2",
|
||||
"version": "0.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/domains.git",
|
||||
"reference": "52b654f8a0e170bfa2e54cb47755b256822477c7"
|
||||
"reference": "f333e23e721ca5cd3bd21063fa88304114b0467d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/domains/zipball/52b654f8a0e170bfa2e54cb47755b256822477c7",
|
||||
"reference": "52b654f8a0e170bfa2e54cb47755b256822477c7",
|
||||
"url": "https://api.github.com/repos/utopia-php/domains/zipball/f333e23e721ca5cd3bd21063fa88304114b0467d",
|
||||
"reference": "f333e23e721ca5cd3bd21063fa88304114b0467d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4115,9 +4115,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/domains/issues",
|
||||
"source": "https://github.com/utopia-php/domains/tree/0.9.2"
|
||||
"source": "https://github.com/utopia-php/domains/tree/0.11.0"
|
||||
},
|
||||
"time": "2025-11-26T12:16:36+00:00"
|
||||
"time": "2026-01-13T09:40:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dsn",
|
||||
@@ -4168,22 +4168,22 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/emails",
|
||||
"version": "0.6.4",
|
||||
"version": "0.6.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/emails.git",
|
||||
"reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52"
|
||||
"reference": "178e57a0f9a24139500c94ce73d166800197b6cf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/emails/zipball/fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52",
|
||||
"reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52",
|
||||
"url": "https://api.github.com/repos/utopia-php/emails/zipball/178e57a0f9a24139500c94ce73d166800197b6cf",
|
||||
"reference": "178e57a0f9a24139500c94ce73d166800197b6cf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/cli": "^0.15",
|
||||
"utopia-php/domains": "^0.9",
|
||||
"utopia-php/domains": "^0.11",
|
||||
"utopia-php/fetch": "^0.5",
|
||||
"utopia-php/validators": "0.*"
|
||||
},
|
||||
@@ -4222,9 +4222,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/emails/issues",
|
||||
"source": "https://github.com/utopia-php/emails/tree/0.6.4"
|
||||
"source": "https://github.com/utopia-php/emails/tree/0.6.5"
|
||||
},
|
||||
"time": "2025-12-18T16:36:50+00:00"
|
||||
"time": "2026-01-13T09:55:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/fetch",
|
||||
@@ -4267,23 +4267,23 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/framework",
|
||||
"version": "0.33.36",
|
||||
"version": "0.33.37",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/http.git",
|
||||
"reference": "fd835ed77e1cdf327067ce4e650cce86304e7098"
|
||||
"reference": "30a119d76531d89da9240496940c84fcd9e1758b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/http/zipball/fd835ed77e1cdf327067ce4e650cce86304e7098",
|
||||
"reference": "fd835ed77e1cdf327067ce4e650cce86304e7098",
|
||||
"url": "https://api.github.com/repos/utopia-php/http/zipball/30a119d76531d89da9240496940c84fcd9e1758b",
|
||||
"reference": "30a119d76531d89da9240496940c84fcd9e1758b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3",
|
||||
"utopia-php/compression": "0.1.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/validators": "0.1.*"
|
||||
"utopia-php/validators": "0.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
@@ -4309,9 +4309,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/http/issues",
|
||||
"source": "https://github.com/utopia-php/http/tree/0.33.36"
|
||||
"source": "https://github.com/utopia-php/http/tree/0.33.37"
|
||||
},
|
||||
"time": "2026-01-12T07:32:29+00:00"
|
||||
"time": "2026-01-13T10:10:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/image",
|
||||
@@ -4516,16 +4516,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "1.3.13",
|
||||
"version": "1.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715"
|
||||
"reference": "52ca4234d8229b68e27e052248734a08784d9d3d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/c5e3f5e970e62e8f7db97b5b90baae2af800a715",
|
||||
"reference": "c5e3f5e970e62e8f7db97b5b90baae2af800a715",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/52ca4234d8229b68e27e052248734a08784d9d3d",
|
||||
"reference": "52ca4234d8229b68e27e052248734a08784d9d3d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4534,7 +4534,7 @@
|
||||
"ext-openssl": "*",
|
||||
"php": ">=8.1",
|
||||
"utopia-php/console": "0.0.*",
|
||||
"utopia-php/database": "3.*",
|
||||
"utopia-php/database": "4.*",
|
||||
"utopia-php/dsn": "0.2.*",
|
||||
"utopia-php/storage": "0.18.*"
|
||||
},
|
||||
@@ -4565,9 +4565,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/1.3.13"
|
||||
"source": "https://github.com/utopia-php/migration/tree/1.4.3"
|
||||
},
|
||||
"time": "2026-01-07T14:48:05+00:00"
|
||||
"time": "2026-01-13T09:51:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
@@ -4954,6 +4954,49 @@
|
||||
},
|
||||
"time": "2021-03-10T10:45:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/span",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/span.git",
|
||||
"reference": "f2f6c499ded3a776e8019902e83d140ff0f89693"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/span/zipball/f2f6c499ded3a776e8019902e83d140ff0f89693",
|
||||
"reference": "f2f6c499ded3a776e8019902e83d140ff0f89693",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.0",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"swoole/ide-helper": "^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-swoole": "Required for coroutine-based storage"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Utopia\\Span\\": "src/Span/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Simple span tracing library for PHP with coroutine support",
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/span/issues",
|
||||
"source": "https://github.com/utopia-php/span/tree/1.0.0"
|
||||
},
|
||||
"time": "2026-01-12T20:05:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/storage",
|
||||
"version": "0.18.18",
|
||||
@@ -5014,22 +5057,22 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/swoole",
|
||||
"version": "0.8.6",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/swoole.git",
|
||||
"reference": "14b00277c35a258cb263706fd4e05c50368feb4f"
|
||||
"reference": "95a937acb393dbf95cccba239d55886e2848ab0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/14b00277c35a258cb263706fd4e05c50368feb4f",
|
||||
"reference": "14b00277c35a258cb263706fd4e05c50368feb4f",
|
||||
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/95a937acb393dbf95cccba239d55886e2848ab0b",
|
||||
"reference": "95a937acb393dbf95cccba239d55886e2848ab0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-swoole": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/framework": "0.33.36"
|
||||
"utopia-php/framework": "0.33.37"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.2.*",
|
||||
@@ -5059,9 +5102,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/swoole/issues",
|
||||
"source": "https://github.com/utopia-php/swoole/tree/0.8.6"
|
||||
"source": "https://github.com/utopia-php/swoole/tree/1.0.0"
|
||||
},
|
||||
"time": "2026-01-12T07:57:35+00:00"
|
||||
"time": "2026-01-14T14:00:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/system",
|
||||
@@ -5171,16 +5214,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/validators",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/validators.git",
|
||||
"reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080"
|
||||
"reference": "30b6030a5b100fc1dff34506e5053759594b2a20"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/validators/zipball/5c57d5b6cf964f8981807c1d3ea8df620c869080",
|
||||
"reference": "5c57d5b6cf964f8981807c1d3ea8df620c869080",
|
||||
"url": "https://api.github.com/repos/utopia-php/validators/zipball/30b6030a5b100fc1dff34506e5053759594b2a20",
|
||||
"reference": "30b6030a5b100fc1dff34506e5053759594b2a20",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5188,7 +5231,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpstan/phpstan": "2.*",
|
||||
"phpunit/phpunit": "11.*"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -5210,9 +5253,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/validators/issues",
|
||||
"source": "https://github.com/utopia-php/validators/tree/0.1.0"
|
||||
"source": "https://github.com/utopia-php/validators/tree/0.2.0"
|
||||
},
|
||||
"time": "2025-11-18T11:05:46+00:00"
|
||||
"time": "2026-01-13T09:16:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/vcs",
|
||||
@@ -5439,16 +5482,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "1.8.9",
|
||||
"version": "1.8.16",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "5fc210f7403f9ecfa068cd2a74210ec6e2a3cec1"
|
||||
"reference": "e2963002b39f3aa24bd6bf61a78492e182397174"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5fc210f7403f9ecfa068cd2a74210ec6e2a3cec1",
|
||||
"reference": "5fc210f7403f9ecfa068cd2a74210ec6e2a3cec1",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e2963002b39f3aa24bd6bf61a78492e182397174",
|
||||
"reference": "e2963002b39f3aa24bd6bf61a78492e182397174",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5484,9 +5527,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/1.8.9"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.8.16"
|
||||
},
|
||||
"time": "2026-01-02T12:09:51+00:00"
|
||||
"time": "2026-01-15T08:16:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -8945,9 +8988,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"utopia-php/audit": 5
|
||||
},
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# Change Log
|
||||
|
||||
## 13.0.0
|
||||
|
||||
- Mark release as stable
|
||||
- Feat: add pull sync on destruction of remote resources (+ confirmation)
|
||||
- Fix: refine zod schema to check string size
|
||||
- Validate using zod schema during push cli command
|
||||
- Maintain order of keys in local config
|
||||
|
||||
## 13.0.0-rc.5
|
||||
|
||||
- Fix push all command not working correctly
|
||||
|
||||
## 13.0.0-rc.4
|
||||
|
||||
- Fix CLI ES module import issues
|
||||
|
||||
## 13.0.0-rc.3
|
||||
|
||||
- Add `Schema` class for programmatically pushing and pulling appwrite config
|
||||
- Add client side db generation using `schema.db.generate()` command
|
||||
|
||||
## 13.0.0-rc.2
|
||||
|
||||
- Fixes a lot of typescript errors throughout the codebase
|
||||
|
||||
## 13.0.0-rc.1
|
||||
|
||||
- Migrates codebase from JavaScript to TypeScript
|
||||
|
||||
## 12.0.1
|
||||
|
||||
Fix type generation for `point`, `lineString` and `polygon` columns
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Change Log
|
||||
|
||||
## 20.1.1
|
||||
|
||||
* Fix boolean parameter not handled correctly in Client requests
|
||||
|
||||
## 20.1.0
|
||||
|
||||
* Added ability to create columns and indexes synchronously while creating a table
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Change Log
|
||||
|
||||
## 20.3.3
|
||||
|
||||
* Fix boolean parameter not handled correctly in Client requests
|
||||
|
||||
## 20.3.2
|
||||
|
||||
* Fix OAuth2 browser infinite redirect issue
|
||||
|
||||
@@ -20,10 +20,12 @@ use Utopia\Database\Validator\Authorization;
|
||||
class TransactionState
|
||||
{
|
||||
private Database $dbForProject;
|
||||
|
||||
public function __construct(Database $dbForProject)
|
||||
private Authorization $authorization;
|
||||
/** @var Authorization $authorization */
|
||||
public function __construct(Database $dbForProject, Authorization $authorization)
|
||||
{
|
||||
$this->dbForProject = $dbForProject;
|
||||
$this->authorization = $authorization;
|
||||
}
|
||||
|
||||
|
||||
@@ -342,12 +344,12 @@ class TransactionState
|
||||
*/
|
||||
private function getTransactionState(string $transactionId): array
|
||||
{
|
||||
$transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId));
|
||||
$transaction = $this->authorization->skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId));
|
||||
if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [
|
||||
$operations = $this->authorization->skip(fn () => $this->dbForProject->find('transactionLogs', [
|
||||
Query::equal('transactionInternalId', [$transaction->getSequence()]),
|
||||
Query::orderAsc(),
|
||||
Query::limit(PHP_INT_MAX)
|
||||
|
||||
@@ -100,8 +100,6 @@ abstract class Migration
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
Authorization::disable();
|
||||
Authorization::setDefaultStatus(false);
|
||||
|
||||
$this->collections = Config::getParam('collections', []);
|
||||
|
||||
@@ -129,6 +127,7 @@ abstract class Migration
|
||||
Document $project,
|
||||
Database $dbForProject,
|
||||
Database $dbForPlatform,
|
||||
Authorization $authorization,
|
||||
?callable $getProjectDB = null
|
||||
): self {
|
||||
$this->project = $project;
|
||||
@@ -136,6 +135,9 @@ abstract class Migration
|
||||
$this->dbForPlatform = $dbForPlatform;
|
||||
$this->getProjectDB = $getProjectDB;
|
||||
|
||||
$authorization->disable();
|
||||
$authorization->setDefaultStatus(false);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class Action extends PlatformAction
|
||||
return \dirname(__DIR__, 6);
|
||||
}
|
||||
|
||||
protected function avatarCallback(string $type, string $code, int $width, int $height, int $quality, Response $response): void
|
||||
protected function avatar(string $type, string $code, int $width, int $height, int $quality, Response $response): void
|
||||
{
|
||||
$code = \strtolower($code);
|
||||
$type = \strtolower($type);
|
||||
@@ -58,10 +58,10 @@ class Action extends PlatformAction
|
||||
unset($image);
|
||||
}
|
||||
|
||||
protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger): array
|
||||
protected function getUserGitHub(string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger, Authorization $authorization): array
|
||||
{
|
||||
try {
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
@@ -112,7 +112,7 @@ class Action extends PlatformAction
|
||||
->setAttribute('providerRefreshToken', $refreshToken)
|
||||
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry('')));
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession));
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession));
|
||||
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Throwable $err) {
|
||||
@@ -120,7 +120,7 @@ class Action extends PlatformAction
|
||||
do {
|
||||
$previousAccessToken = $gitHubSession->getAttribute('providerAccessToken');
|
||||
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
$gitHubSession = new Document();
|
||||
|
||||
@@ -59,6 +59,6 @@ class Get extends Action
|
||||
|
||||
public function action(string $code, int $width, int $height, int $quality, Response $response)
|
||||
{
|
||||
$this->avatarCallback('browsers', $code, $width, $height, $quality, $response);
|
||||
$this->avatar('browsers', $code, $width, $height, $quality, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,12 +53,13 @@ class Get extends Action
|
||||
->inject('contributors')
|
||||
->inject('employees')
|
||||
->inject('logger')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger)
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization)
|
||||
{
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
|
||||
if ($user->isEmpty() && empty($mock)) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -68,7 +69,7 @@ class Get extends Action
|
||||
$userId = $user->getId();
|
||||
$email = $user->getAttribute('email', '');
|
||||
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger);
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization);
|
||||
$githubId = $gitHub['id'] ?? '';
|
||||
|
||||
$isHero = \array_key_exists($email, $heroes);
|
||||
|
||||
@@ -53,12 +53,13 @@ class Get extends Action
|
||||
->inject('contributors')
|
||||
->inject('employees')
|
||||
->inject('logger')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger)
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization)
|
||||
{
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
|
||||
if ($user->isEmpty() && empty($mock)) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -69,7 +70,7 @@ class Get extends Action
|
||||
$email = $user->getAttribute('email', '');
|
||||
$createdAt = new \DateTime($user->getCreatedAt());
|
||||
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger);
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization);
|
||||
$githubName = $gitHub['name'] ?? '';
|
||||
$githubId = $gitHub['id'] ?? '';
|
||||
|
||||
|
||||
@@ -53,12 +53,13 @@ class Get extends Action
|
||||
->inject('contributors')
|
||||
->inject('employees')
|
||||
->inject('logger')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger)
|
||||
public function action(string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $authorization)
|
||||
{
|
||||
$user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
$user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId));
|
||||
|
||||
if ($user->isEmpty() && empty($mock)) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -73,7 +74,7 @@ class Get extends Action
|
||||
$email = $user->getAttribute('email', '');
|
||||
$createdAt = new \DateTime($user->getCreatedAt());
|
||||
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger);
|
||||
$gitHub = $this->getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization);
|
||||
$githubName = $gitHub['name'] ?? '';
|
||||
$githubId = $gitHub['id'] ?? '';
|
||||
|
||||
|
||||
@@ -59,6 +59,6 @@ class Get extends Action
|
||||
|
||||
public function action(string $code, int $width, int $height, int $quality, Response $response)
|
||||
{
|
||||
$this->avatarCallback('credit-cards', $code, $width, $height, $quality, $response);
|
||||
$this->avatar('credit-cards', $code, $width, $height, $quality, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,6 @@ class Get extends Action
|
||||
|
||||
public function action(string $code, int $width, int $height, int $quality, Response $response)
|
||||
{
|
||||
$this->avatarCallback('flags', $code, $width, $height, $quality, $response);
|
||||
$this->avatar('flags', $code, $width, $height, $quality, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Swoole\Request;
|
||||
use Utopia\System\System;
|
||||
@@ -142,7 +143,7 @@ class Base extends Action
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, Authorization $authorization, string $referenceType = 'branch', string $reference = ''): Document
|
||||
{
|
||||
$deploymentId = ID::unique();
|
||||
$providerInstallationId = $installation->getAttribute('providerInstallationId', '');
|
||||
@@ -239,7 +240,7 @@ class Base extends Action
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
$ruleId = $isMd5 ? md5($domain) : ID::unique();
|
||||
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -265,7 +266,7 @@ class Base extends Action
|
||||
$domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -302,7 +303,7 @@ class Base extends Action
|
||||
$domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
$authorization->skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
@@ -328,6 +329,8 @@ class Base extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateEmptyManualRule($project, $site, $deployment, $dbForPlatform, $authorization);
|
||||
|
||||
$queueForBuilds
|
||||
->setType(BUILD_TYPE_DEPLOYMENT)
|
||||
->setResource($site)
|
||||
@@ -336,4 +339,34 @@ class Base extends Action
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update empty manual rule for deployment.
|
||||
* In case of first deployment, deployment ID will be empty in the rules, so we need to update it here.
|
||||
*
|
||||
* @param \Utopia\Database\Document $project
|
||||
* @param \Utopia\Database\Document $resource
|
||||
* @param \Utopia\Database\Document $deployment
|
||||
* @param \Utopia\Database\Database $dbForPlatform
|
||||
* @return void
|
||||
*/
|
||||
public static function updateEmptyManualRule(Document $project, Document $resource, Document $deployment, Database $dbForPlatform, Authorization $authorization)
|
||||
{
|
||||
$resourceType = $resource->getCollection() === 'sites' ? 'site' : 'function';
|
||||
|
||||
$queries = [
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
Query::equal('deploymentResourceInternalId', [$resource->getSequence()]),
|
||||
Query::equal('deploymentResourceType', [$resourceType]),
|
||||
Query::equal('deploymentId', ['']),
|
||||
Query::equal('type', ['deployment']),
|
||||
Query::equal('trigger', ['manual']),
|
||||
];
|
||||
$dbForPlatform->forEach('rules', function (Document $rule) use ($deployment, $dbForPlatform, $authorization) {
|
||||
$authorization->skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), new Document([
|
||||
'deploymentId' => $deployment->getId(),
|
||||
'deploymentInternalId' => $deployment->getSequence(),
|
||||
])));
|
||||
}, $queries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ class Get extends Action
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('platform')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -68,7 +69,8 @@ class Get extends Action
|
||||
string $type,
|
||||
Response $response,
|
||||
Database $dbForPlatform,
|
||||
array $platform
|
||||
array $platform,
|
||||
Authorization $authorization,
|
||||
) {
|
||||
$domains = $platform['hostnames'] ?? [];
|
||||
if ($type === 'rules') {
|
||||
@@ -121,7 +123,7 @@ class Get extends Action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||
}
|
||||
|
||||
$document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
||||
$document = $authorization->skip(fn () => $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$value]),
|
||||
]));
|
||||
|
||||
|
||||
+5
-5
@@ -292,7 +292,7 @@ abstract class Action extends UtopiaAction
|
||||
};
|
||||
}
|
||||
|
||||
protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document
|
||||
protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): Document
|
||||
{
|
||||
$key = $attribute->getAttribute('key');
|
||||
$type = $attribute->getAttribute('type', '');
|
||||
@@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction
|
||||
throw new Exception($this->getSpatialTypeNotSupportedException(), params: [$type]);
|
||||
}
|
||||
|
||||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
@@ -371,7 +371,7 @@ abstract class Action extends UtopiaAction
|
||||
\in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) &&
|
||||
$attribute->getAttribute('required')
|
||||
) {
|
||||
$hasData = !Authorization::skip(fn () => $dbForProject
|
||||
$hasData = !$authorization->skip(fn () => $dbForProject
|
||||
->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence()))
|
||||
->isEmpty();
|
||||
|
||||
@@ -472,9 +472,9 @@ abstract class Action extends UtopiaAction
|
||||
return $attribute;
|
||||
}
|
||||
|
||||
protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document
|
||||
protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, Authorization $authorization, string $type, int $size = null, string $filter = null, string|bool|int|float|array $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document
|
||||
{
|
||||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -69,10 +70,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute($databaseId, $collectionId, new Document([
|
||||
'key' => $key,
|
||||
@@ -81,7 +83,7 @@ class Create extends Action
|
||||
'required' => $required,
|
||||
'default' => $default,
|
||||
'array' => $array,
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -68,10 +69,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -79,6 +81,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_BOOLEAN,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+5
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -70,10 +71,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute(
|
||||
$databaseId,
|
||||
@@ -90,7 +92,8 @@ class Create extends Action
|
||||
$response,
|
||||
$dbForProject,
|
||||
$queueForDatabase,
|
||||
$queueForEvents
|
||||
$queueForEvents,
|
||||
$authorization
|
||||
);
|
||||
|
||||
$response
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_DATETIME,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+3
-2
@@ -67,12 +67,13 @@ class Delete extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
+5
-2
@@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -70,10 +71,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute(
|
||||
$databaseId,
|
||||
@@ -90,7 +92,8 @@ class Create extends Action
|
||||
$response,
|
||||
$dbForProject,
|
||||
$queueForDatabase,
|
||||
$queueForEvents
|
||||
$queueForEvents,
|
||||
$authorization
|
||||
);
|
||||
|
||||
$response
|
||||
|
||||
+4
-1
@@ -12,6 +12,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_STRING,
|
||||
filter: APP_DATABASE_ATTRIBUTE_EMAIL,
|
||||
default: $default,
|
||||
|
||||
+5
-2
@@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -73,10 +74,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
if (!is_null($default) && !\in_array($default, $elements, true)) {
|
||||
throw new Exception($this->getInvalidValueException(), 'Default value not found in elements');
|
||||
@@ -98,7 +100,8 @@ class Create extends Action
|
||||
$response,
|
||||
$dbForProject,
|
||||
$queueForDatabase,
|
||||
$queueForEvents
|
||||
$queueForEvents,
|
||||
$authorization
|
||||
);
|
||||
|
||||
$response
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -71,10 +72,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -82,6 +84,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_STRING,
|
||||
filter: APP_DATABASE_ATTRIBUTE_ENUM,
|
||||
default: $default,
|
||||
|
||||
+4
-2
@@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -74,10 +75,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$min ??= -PHP_FLOAT_MAX;
|
||||
$max ??= PHP_FLOAT_MAX;
|
||||
@@ -100,7 +102,7 @@ class Create extends Action
|
||||
'array' => $array,
|
||||
'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE,
|
||||
'formatOptions' => ['min' => $min, 'max' => $max],
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$formatOptions = $attribute->getAttribute('formatOptions', []);
|
||||
if (!empty($formatOptions)) {
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -71,10 +72,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -82,6 +84,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_FLOAT,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+3
-2
@@ -68,12 +68,13 @@ class Get extends Action
|
||||
->param('key', '', new Key(), 'Attribute Key.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
+5
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -70,10 +71,11 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute(
|
||||
$databaseId,
|
||||
@@ -90,7 +92,8 @@ class Create extends Action
|
||||
$response,
|
||||
$dbForProject,
|
||||
$queueForDatabase,
|
||||
$queueForEvents
|
||||
$queueForEvents,
|
||||
$authorization
|
||||
);
|
||||
|
||||
$response
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_STRING,
|
||||
filter: APP_DATABASE_ATTRIBUTE_IP,
|
||||
default: $default,
|
||||
|
||||
+7
-5
@@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -66,18 +67,19 @@ class Create extends Action
|
||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||
->param('key', '', new Key(), 'Attribute Key.')
|
||||
->param('required', null, new Boolean(), 'Is attribute required?')
|
||||
->param('min', null, new Nullable(new Integer()), 'Minimum value', true)
|
||||
->param('max', null, new Nullable(new Integer()), 'Maximum value', true)
|
||||
->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when attribute is required.', true)
|
||||
->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true)
|
||||
->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true)
|
||||
->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when attribute is required.', true)
|
||||
->param('array', false, new Boolean(), 'Is attribute an array?', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$min ??= \PHP_INT_MIN;
|
||||
$max ??= \PHP_INT_MAX;
|
||||
@@ -102,7 +104,7 @@ class Create extends Action
|
||||
'array' => $array,
|
||||
'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE,
|
||||
'formatOptions' => ['min' => $min, 'max' => $max],
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$formatOptions = $attribute->getAttribute('formatOptions', []);
|
||||
if (!empty($formatOptions)) {
|
||||
|
||||
+7
-4
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -64,17 +65,18 @@ class Update extends Action
|
||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||
->param('key', '', new Key(), 'Attribute Key.')
|
||||
->param('required', null, new Boolean(), 'Is attribute required?')
|
||||
->param('min', null, new Nullable(new Integer()), 'Minimum value', true)
|
||||
->param('max', null, new Nullable(new Integer()), 'Maximum value', true)
|
||||
->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when attribute is required.')
|
||||
->param('min', null, new Nullable(new Integer(false, 64)), 'Minimum value', true)
|
||||
->param('max', null, new Nullable(new Integer(false, 64)), 'Maximum value', true)
|
||||
->param('default', null, new Nullable(new Integer(false, 64)), 'Default value. Cannot be set when attribute is required.')
|
||||
->param('newKey', null, new Nullable(new Key()), 'New Attribute Key.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -82,6 +84,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_INTEGER,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,17 +70,18 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute($databaseId, $collectionId, new Document([
|
||||
'key' => $key,
|
||||
'type' => Database::VAR_LINESTRING,
|
||||
'required' => $required,
|
||||
'default' => $default
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_LINESTRING,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,17 +70,18 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute($databaseId, $collectionId, new Document([
|
||||
'key' => $key,
|
||||
'type' => Database::VAR_POINT,
|
||||
'required' => $required,
|
||||
'default' => $default,
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_POINT,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,17 +70,18 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->createAttribute($databaseId, $collectionId, new Document([
|
||||
'key' => $key,
|
||||
'type' => Database::VAR_POLYGON,
|
||||
'required' => $required,
|
||||
'default' => $default,
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\Spatial;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -69,10 +70,11 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?array $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -80,6 +82,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_POLYGON,
|
||||
default: $default,
|
||||
required: $required,
|
||||
|
||||
+4
-3
@@ -83,16 +83,17 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$key ??= $relatedCollectionId;
|
||||
$twoWayKeyWasProvided = $twoWayKey !== null;
|
||||
$twoWayKey ??= $collectionId;
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
@@ -154,7 +155,7 @@ class Create extends Action
|
||||
'twoWayKey' => $twoWayKey,
|
||||
'onDelete' => $onDelete,
|
||||
]
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
foreach ($attribute->getAttribute('options', []) as $k => $option) {
|
||||
$attribute->setAttribute($k, $option);
|
||||
|
||||
+5
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -71,6 +72,7 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -82,7 +84,8 @@ class Update extends Action
|
||||
?string $newKey,
|
||||
UtopiaResponse $response,
|
||||
Database $dbForProject,
|
||||
Event $queueForEvents
|
||||
Event $queueForEvents,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -90,6 +93,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_RELATIONSHIP,
|
||||
required: false,
|
||||
options: [
|
||||
|
||||
+6
-2
@@ -14,6 +14,7 @@ use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -77,6 +78,7 @@ class Create extends Action
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -93,7 +95,8 @@ class Create extends Action
|
||||
Database $dbForProject,
|
||||
EventDatabase $queueForDatabase,
|
||||
Event $queueForEvents,
|
||||
array $plan
|
||||
array $plan,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.');
|
||||
@@ -132,7 +135,8 @@ class Create extends Action
|
||||
$response,
|
||||
$dbForProject,
|
||||
$queueForDatabase,
|
||||
$queueForEvents
|
||||
$queueForEvents,
|
||||
$authorization
|
||||
);
|
||||
|
||||
$attribute->setAttribute('encrypt', $encrypt);
|
||||
|
||||
+5
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -72,6 +73,7 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -85,7 +87,8 @@ class Update extends Action
|
||||
?string $newKey,
|
||||
UtopiaResponse $response,
|
||||
Database $dbForProject,
|
||||
Event $queueForEvents
|
||||
Event $queueForEvents,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$attribute = $this->updateAttribute(
|
||||
databaseId: $databaseId,
|
||||
@@ -93,6 +96,7 @@ class Update extends Action
|
||||
key: $key,
|
||||
dbForProject: $dbForProject,
|
||||
queueForEvents: $queueForEvents,
|
||||
authorization: $authorization,
|
||||
type: Database::VAR_STRING,
|
||||
size: $size,
|
||||
default: $default,
|
||||
|
||||
+5
-2
@@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -70,6 +71,7 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -83,7 +85,8 @@ class Create extends Action
|
||||
UtopiaResponse $response,
|
||||
Database $dbForProject,
|
||||
EventDatabase $queueForDatabase,
|
||||
Event $queueForEvents
|
||||
Event $queueForEvents,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$attribute = $this->createAttribute($databaseId, $collectionId, new Document([
|
||||
'key' => $key,
|
||||
@@ -93,7 +96,7 @@ class Create extends Action
|
||||
'default' => $default,
|
||||
'array' => $array,
|
||||
'format' => APP_DATABASE_ATTRIBUTE_URL,
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
|
||||
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization);
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
|
||||
|
||||
+5
-1
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Key;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -69,6 +70,7 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -81,7 +83,8 @@ class Update extends Action
|
||||
?string $newKey,
|
||||
UtopiaResponse $response,
|
||||
Database $dbForProject,
|
||||
Event $queueForEvents
|
||||
Event $queueForEvents,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$attribute = $this->updateAttribute(
|
||||
$databaseId,
|
||||
@@ -89,6 +92,7 @@ class Update extends Action
|
||||
$key,
|
||||
$dbForProject,
|
||||
$queueForEvents,
|
||||
$authorization,
|
||||
type: Database::VAR_STRING,
|
||||
filter: APP_DATABASE_ATTRIBUTE_URL,
|
||||
default: $default,
|
||||
|
||||
+3
-2
@@ -64,12 +64,13 @@ class XList extends Action
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
@@ -85,12 +85,13 @@ class Create extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, array $attributes, array $indexes, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
@@ -185,7 +186,13 @@ class Create extends Action
|
||||
$dbForProject->getAdapter()->getSupportForVectors(),
|
||||
$dbForProject->getAdapter()->getSupportForAttributes(),
|
||||
$dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForIdenticalIndexes()
|
||||
$dbForProject->getAdapter()->getSupportForIdenticalIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForObjectIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForTrigramIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForSpatialAttributes(),
|
||||
$dbForProject->getAdapter()->getSupportForIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForUniqueIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForFulltextIndex(),
|
||||
);
|
||||
|
||||
foreach ($collectionIndexes as $indexDoc) {
|
||||
|
||||
@@ -64,12 +64,13 @@ class Delete extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
+4
-3
@@ -258,9 +258,9 @@ abstract class Action extends DatabasesAction
|
||||
Document $collection,
|
||||
Document $document,
|
||||
Database $dbForProject,
|
||||
|
||||
/* options */
|
||||
array &$collectionsCache,
|
||||
Authorization $authorization,
|
||||
?int &$operations = null,
|
||||
): bool {
|
||||
|
||||
@@ -297,7 +297,7 @@ abstract class Action extends DatabasesAction
|
||||
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
|
||||
|
||||
if (!isset($collectionsCache[$relatedCollectionId])) {
|
||||
$relatedCollectionDoc = Authorization::skip(
|
||||
$relatedCollectionDoc = $authorization->skip(
|
||||
fn () => $dbForProject->getDocument(
|
||||
'database_' . $database->getSequence(),
|
||||
$relatedCollectionId
|
||||
@@ -323,7 +323,8 @@ abstract class Action extends DatabasesAction
|
||||
document: $relation,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
operations: $operations
|
||||
operations: $operations,
|
||||
authorization: $authorization
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -85,20 +85,21 @@ class Decrement extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
}
|
||||
@@ -106,7 +107,7 @@ class Decrement extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction');
|
||||
|
||||
+7
-6
@@ -85,20 +85,21 @@ class Increment extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
}
|
||||
@@ -106,7 +107,7 @@ class Increment extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction');
|
||||
|
||||
+25
-18
@@ -24,6 +24,7 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Authorization\Input;
|
||||
use Utopia\Database\Validator\Permissions;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Swoole\Response as SwooleResponse;
|
||||
@@ -132,9 +133,10 @@ class Create extends Action
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$data = \is_string($data)
|
||||
? \json_decode($data, true)
|
||||
@@ -178,19 +180,19 @@ class Create extends Action
|
||||
$documents = [$data];
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($isBulk && !$isAPIKey && !$isPrivilegedUser) {
|
||||
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE);
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
}
|
||||
@@ -204,7 +206,7 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext());
|
||||
}
|
||||
|
||||
$setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) {
|
||||
$setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) {
|
||||
$allowedPermissions = [
|
||||
Database::PERMISSION_READ,
|
||||
Database::PERMISSION_UPDATE,
|
||||
@@ -247,8 +249,8 @@ class Create extends Action
|
||||
$permission->getIdentifier(),
|
||||
$permission->getDimension()
|
||||
))->toString();
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')');
|
||||
if (!$authorization->hasRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,21 +261,25 @@ class Create extends Action
|
||||
|
||||
$operations = 0;
|
||||
|
||||
$checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations) {
|
||||
$checkPermissions = function (Document $collection, Document $document, string $permission) use ($isAPIKey, $isPrivilegedUser, &$checkPermissions, $dbForProject, $database, &$operations, $authorization) {
|
||||
$operations++;
|
||||
|
||||
$documentSecurity = $collection->getAttribute('documentSecurity', false);
|
||||
$validator = new Authorization($permission);
|
||||
|
||||
$valid = $validator->isValid($collection->getPermissionsByType($permission));
|
||||
if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
$validCollection = $authorization->isValid(
|
||||
new Input($permission, $collection->getPermissionsByType($permission))
|
||||
);
|
||||
if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription());
|
||||
}
|
||||
|
||||
if ($permission === Database::PERMISSION_UPDATE) {
|
||||
$valid = $valid || $validator->isValid($document->getUpdate());
|
||||
$validDocument = $authorization->isValid(
|
||||
new Input($permission, $document->getUpdate())
|
||||
);
|
||||
$valid = $validCollection || $validDocument;
|
||||
if ($documentSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +304,7 @@ class Create extends Action
|
||||
}
|
||||
|
||||
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
|
||||
$relatedCollection = Authorization::skip(
|
||||
$relatedCollection = $authorization->skip(
|
||||
fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)
|
||||
);
|
||||
|
||||
@@ -314,7 +320,7 @@ class Create extends Action
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
$current = Authorization::skip(
|
||||
$current = $authorization->skip(
|
||||
fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId())
|
||||
);
|
||||
|
||||
@@ -369,7 +375,7 @@ class Create extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty()) {
|
||||
throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]);
|
||||
@@ -468,6 +474,7 @@ class Create extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
authorization: $authorization
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -83,6 +83,7 @@ class Delete extends Action
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -97,18 +98,19 @@ class Delete extends Action
|
||||
Event $queueForEvents,
|
||||
StatsUsage $queueForStatsUsage,
|
||||
TransactionState $transactionState,
|
||||
array $plan
|
||||
array $plan,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
@@ -121,7 +123,7 @@ class Delete extends Action
|
||||
// Use transaction-aware document retrieval to see changes from same transaction
|
||||
$document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
|
||||
} else {
|
||||
$document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
$document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
}
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
@@ -131,7 +133,7 @@ class Delete extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty()) {
|
||||
throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]);
|
||||
@@ -205,6 +207,7 @@ class Delete extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
authorization: $authorization
|
||||
);
|
||||
|
||||
$queueForStatsUsage
|
||||
|
||||
+7
-5
@@ -70,20 +70,21 @@ class Get extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void
|
||||
{
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
@@ -125,6 +126,7 @@ class Get extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
authorization: $authorization,
|
||||
operations: $operations
|
||||
);
|
||||
|
||||
|
||||
+3
-2
@@ -72,13 +72,14 @@ class XList extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('authorization')
|
||||
->inject('audit')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
+14
-12
@@ -87,10 +87,11 @@ class Update extends Action
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
@@ -98,16 +99,16 @@ class Update extends Action
|
||||
throw new Exception($this->getMissingPayloadException());
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
@@ -125,7 +126,7 @@ class Update extends Action
|
||||
// Use transaction-aware document retrieval to see changes from same transaction
|
||||
$document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
|
||||
} else {
|
||||
$document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
$document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
}
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
@@ -140,7 +141,7 @@ class Update extends Action
|
||||
]);
|
||||
|
||||
// Users can only manage their own roles, API keys and Admin users can manage any
|
||||
$roles = Authorization::getRoles();
|
||||
$roles = $authorization->getRoles();
|
||||
if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) {
|
||||
foreach (Database::PERMISSIONS as $type) {
|
||||
foreach ($permissions as $permission) {
|
||||
@@ -153,7 +154,7 @@ class Update extends Action
|
||||
$permission->getIdentifier(),
|
||||
$permission->getDimension()
|
||||
))->toString();
|
||||
if (!Authorization::isRole($role)) {
|
||||
if (!$authorization->hasRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
@@ -171,7 +172,7 @@ class Update extends Action
|
||||
|
||||
$operations = 0;
|
||||
|
||||
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) {
|
||||
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) {
|
||||
$operations++;
|
||||
|
||||
$relationships = \array_filter(
|
||||
@@ -195,7 +196,7 @@ class Update extends Action
|
||||
}
|
||||
|
||||
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
|
||||
$relatedCollection = Authorization::skip(
|
||||
$relatedCollection = $authorization->skip(
|
||||
fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)
|
||||
);
|
||||
|
||||
@@ -212,7 +213,7 @@ class Update extends Action
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
$oldDocument = Authorization::skip(fn () => $dbForProject->getDocument(
|
||||
$oldDocument = $authorization->skip(fn () => $dbForProject->getDocument(
|
||||
'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(),
|
||||
$relation->getId()
|
||||
));
|
||||
@@ -249,7 +250,7 @@ class Update extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty()) {
|
||||
throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]);
|
||||
@@ -340,6 +341,7 @@ class Update extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
authorization: $authorization,
|
||||
);
|
||||
|
||||
$response->dynamic($document, $this->getResponseModel());
|
||||
|
||||
+14
-12
@@ -91,10 +91,11 @@ class Upsert extends Action
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
@@ -106,15 +107,15 @@ class Upsert extends Action
|
||||
throw new Exception($this->getMissingPayloadException());
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
}
|
||||
@@ -139,7 +140,7 @@ class Upsert extends Action
|
||||
// Use transaction-aware document retrieval to see changes from same transaction
|
||||
$oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId);
|
||||
} else {
|
||||
$oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
$oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId));
|
||||
}
|
||||
if ($oldDocument->isEmpty()) {
|
||||
if (!empty($user->getId())) {
|
||||
@@ -155,7 +156,7 @@ class Upsert extends Action
|
||||
}
|
||||
|
||||
// Users can only manage their own roles, API keys and Admin users can manage any
|
||||
$roles = Authorization::getRoles();
|
||||
$roles = $authorization->getRoles();
|
||||
if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) {
|
||||
foreach (Database::PERMISSIONS as $type) {
|
||||
foreach ($permissions as $permission) {
|
||||
@@ -168,7 +169,7 @@ class Upsert extends Action
|
||||
$permission->getIdentifier(),
|
||||
$permission->getDimension()
|
||||
))->toString();
|
||||
if (!Authorization::isRole($role)) {
|
||||
if (!$authorization->hasRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
@@ -181,7 +182,7 @@ class Upsert extends Action
|
||||
$newDocument = new Document($data);
|
||||
$operations = 0;
|
||||
|
||||
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations) {
|
||||
$setCollection = (function (Document $collection, Document $document) use ($isAPIKey, $isPrivilegedUser, &$setCollection, $dbForProject, $database, &$operations, $authorization) {
|
||||
$operations++;
|
||||
|
||||
$relationships = \array_filter(
|
||||
@@ -205,7 +206,7 @@ class Upsert extends Action
|
||||
}
|
||||
|
||||
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
|
||||
$relatedCollection = Authorization::skip(
|
||||
$relatedCollection = $authorization->skip(
|
||||
fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)
|
||||
);
|
||||
|
||||
@@ -222,7 +223,7 @@ class Upsert extends Action
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
$oldDocument = Authorization::skip(fn () => $dbForProject->getDocument(
|
||||
$oldDocument = $authorization->skip(fn () => $dbForProject->getDocument(
|
||||
'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(),
|
||||
$relation->getId()
|
||||
));
|
||||
@@ -259,7 +260,7 @@ class Upsert extends Action
|
||||
// Handle transaction staging
|
||||
if ($transactionId !== null) {
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
: $dbForProject->getDocument('transactions', $transactionId);
|
||||
if ($transaction->isEmpty()) {
|
||||
throw new Exception(Exception::TRANSACTION_NOT_FOUND, params: [$transactionId]);
|
||||
@@ -361,6 +362,7 @@ class Upsert extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
authorization: $authorization
|
||||
);
|
||||
|
||||
$relationships = \array_map(
|
||||
|
||||
+9
-7
@@ -74,20 +74,21 @@ class XList extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void
|
||||
{
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
$collection = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId));
|
||||
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception($this->getParentNotFoundException(), params: [$collectionId]);
|
||||
}
|
||||
@@ -115,7 +116,7 @@ class XList extends Action
|
||||
|
||||
$documentId = $cursor->getValue();
|
||||
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
$type = ucfirst($this->getContext());
|
||||
@@ -161,7 +162,8 @@ class XList extends Action
|
||||
document: $document,
|
||||
dbForProject: $dbForProject,
|
||||
collectionsCache: $collectionsCache,
|
||||
operations: $operations,
|
||||
authorization: $authorization,
|
||||
operations: $operations
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,12 +57,13 @@ class Get extends Action
|
||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
||||
+10
-3
@@ -79,12 +79,13 @@ class Create extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
@@ -198,7 +199,13 @@ class Create extends Action
|
||||
$dbForProject->getAdapter()->getSupportForVectors(),
|
||||
$dbForProject->getAdapter()->getSupportForAttributes(),
|
||||
$dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForIdenticalIndexes()
|
||||
$dbForProject->getAdapter()->getSupportForIdenticalIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForObjectIndexes(),
|
||||
$dbForProject->getAdapter()->getSupportForTrigramIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForSpatialAttributes(),
|
||||
$dbForProject->getAdapter()->getSupportForIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForUniqueIndex(),
|
||||
$dbForProject->getAdapter()->getSupportForFulltextIndex(),
|
||||
);
|
||||
|
||||
if (!$validator->isValid($index)) {
|
||||
|
||||
+3
-2
@@ -70,12 +70,13 @@ class Delete extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDatabase')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
||||
@@ -59,12 +59,13 @@ class Get extends Action
|
||||
->param('key', null, new Key(), 'Index Key.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
||||
+4
-3
@@ -66,13 +66,14 @@ class XList extends Action
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
/** @var Document $database */
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
@@ -112,7 +113,7 @@ class XList extends Action
|
||||
}
|
||||
|
||||
$indexId = $cursor->getValue();
|
||||
$cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [
|
||||
$cursorDocument = $authorization->skip(fn () => $dbForProject->find('indexes', [
|
||||
Query::equal('collectionInternalId', [$collection->getSequence()]),
|
||||
Query::equal('databaseInternalId', [$database->getSequence()]),
|
||||
Query::equal('key', [$indexId]),
|
||||
|
||||
@@ -71,13 +71,14 @@ class XList extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('authorization')
|
||||
->inject('audit')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audit): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization, Audit $audit): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
@@ -112,9 +113,9 @@ class XList extends Action
|
||||
$detector = new Detector($log['userAgent']);
|
||||
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
|
||||
|
||||
$os = $detector->getOS();
|
||||
$client = $detector->getClient();
|
||||
$device = $detector->getDevice();
|
||||
$os = $detector->getOS() ?: [];
|
||||
$client = $detector->getClient() ?: [];
|
||||
$device = $detector->getDevice() ?: [];
|
||||
|
||||
$output[$i] = new Document([
|
||||
'event' => $log['event'],
|
||||
@@ -122,20 +123,20 @@ class XList extends Action
|
||||
'userEmail' => $log['data']['userEmail'] ?? null,
|
||||
'userName' => $log['data']['userName'] ?? null,
|
||||
'mode' => $log['data']['mode'] ?? null,
|
||||
'ip' => $log['ip'],
|
||||
'time' => $log['time'],
|
||||
'osCode' => $os['osCode'],
|
||||
'osName' => $os['osName'],
|
||||
'osVersion' => $os['osVersion'],
|
||||
'clientType' => $client['clientType'],
|
||||
'clientCode' => $client['clientCode'],
|
||||
'clientName' => $client['clientName'],
|
||||
'clientVersion' => $client['clientVersion'],
|
||||
'clientEngine' => $client['clientEngine'],
|
||||
'clientEngineVersion' => $client['clientEngineVersion'],
|
||||
'deviceName' => $device['deviceName'],
|
||||
'deviceBrand' => $device['deviceBrand'],
|
||||
'deviceModel' => $device['deviceModel']
|
||||
'ip' => $log['ip'] ?? null,
|
||||
'time' => $log['time'] ?? null,
|
||||
'osCode' => $os['osCode'] ?? null,
|
||||
'osName' => $os['osName'] ?? null,
|
||||
'osVersion' => $os['osVersion'] ?? null,
|
||||
'clientType' => $client['clientType'] ?? null,
|
||||
'clientCode' => $client['clientCode'] ?? null,
|
||||
'clientName' => $client['clientName'] ?? null,
|
||||
'clientVersion' => $client['clientVersion'] ?? null,
|
||||
'clientEngine' => $client['clientEngine'] ?? null,
|
||||
'clientEngineVersion' => $client['clientEngineVersion'] ?? null,
|
||||
'deviceName' => $device['deviceName'] ?? null,
|
||||
'deviceBrand' => $device['deviceBrand'] ?? null,
|
||||
'deviceModel' => $device['deviceModel'] ?? null
|
||||
]);
|
||||
|
||||
$record = $geodb->get($log['ip']);
|
||||
|
||||
@@ -71,12 +71,13 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void
|
||||
public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
}
|
||||
|
||||
@@ -63,10 +63,11 @@ class Get extends Action
|
||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void
|
||||
public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void
|
||||
{
|
||||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
$collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId);
|
||||
@@ -83,7 +84,7 @@ class Get extends Action
|
||||
str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS),
|
||||
];
|
||||
|
||||
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
$authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats) {
|
||||
foreach ($metrics as $metric) {
|
||||
$result = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user