diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11966d14f3..b92361e51a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -320,15 +320,12 @@ These are the current metrics we collect usage stats for: | executions | Total number of executions per project | | databases | Total number of databases per project | | databases.storage | Total amount of storage used by all databases per project (in bytes) | -| databases.storage_disk | Total amount of storage used by all database per project on disk (in bytes) | | collections | Total number of collections per project | | {databaseInternalId}.collections | Total number of collections per database| | {databaseInternalId}.storage | Sum of database storage (in bytes) | -| {databaseInternalId}.storage_disk | Sum of database storage on disk (in bytes) | | documents | Total number of documents per project | | {databaseInternalId}.{collectionInternalId}.documents | Total number of documents per collection | | {databaseInternalId}.{collectionInternalId}.storage | Sum of database storage used by the collection (in bytes) | -| {databsaeInternalId}.{collectionInternalId}.storage_disk | Sum of database storage used by the collection on disk (in bytes) | | buckets | Total number of buckets per project | | files | Total number of files per project | | {bucketInternalId}.files.storage | Sum of files.storage per bucket (in bytes) | diff --git a/app/config/specs/open-api3-1.6.x-client.json b/app/config/specs/open-api3-1.6.x-client.json index fc967c13a6..f1b247a70f 100644 --- a/app/config/specs/open-api3-1.6.x-client.json +++ b/app/config/specs/open-api3-1.6.x-client.json @@ -9405,7 +9405,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/open-api3-1.6.x-console.json b/app/config/specs/open-api3-1.6.x-console.json index 8527e27630..1e3c1a21c4 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -35589,7 +35589,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/open-api3-1.6.x-server.json b/app/config/specs/open-api3-1.6.x-server.json index 7d199f1919..1a394f6def 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -25966,7 +25966,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index fc967c13a6..f1b247a70f 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -9405,7 +9405,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 8527e27630..1e3c1a21c4 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -35589,7 +35589,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 7d199f1919..1a394f6def 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -25966,7 +25966,7 @@ "responseBody": { "type": "string", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-1.6.x-client.json b/app/config/specs/swagger2-1.6.x-client.json index 66b272bea7..cf001af0e8 100644 --- a/app/config/specs/swagger2-1.6.x-client.json +++ b/app/config/specs/swagger2-1.6.x-client.json @@ -9589,9 +9589,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index 58c81422a9..d9037abc55 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -36104,9 +36104,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 1e70715a7e..42cf3ff2c7 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -26458,9 +26458,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 66b272bea7..cf001af0e8 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -9589,9 +9589,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 58c81422a9..d9037abc55 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -36104,9 +36104,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 1e70715a7e..42cf3ff2c7 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -26458,9 +26458,9 @@ "format": "int32" }, "responseBody": { - "type": "string", + "type": "payload", "description": "HTTP response body. This will return empty unless execution is created as synchronous.", - "x-example": "Developers are awesome." + "x-example": "" }, "responseHeaders": { "type": "array", diff --git a/app/init.php b/app/init.php index df75e5b3e0..cf0dbe44ee 100644 --- a/app/init.php +++ b/app/init.php @@ -240,15 +240,12 @@ const METRIC_SESSIONS = 'sessions'; const METRIC_DATABASES = 'databases'; const METRIC_COLLECTIONS = 'collections'; const METRIC_DATABASES_STORAGE = 'databases.storage'; -const METRIC_DATABASES_STORAGE_DISK = 'databases.storage_disk'; const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; const METRIC_DATABASE_ID_STORAGE = '{databaseInternalId}.databases.storage'; -const METRIC_DATABASE_ID_STORAGE_DISK = '{databaseInternalId}.databases.storage_disk'; const METRIC_DOCUMENTS = 'documents'; const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage'; -const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE_DISK = '{databaseInternalId}.{collectionInternalId}.databases.storage_disk'; const METRIC_BUCKETS = 'buckets'; const METRIC_FILES = 'files'; const METRIC_FILES_STORAGE = 'files.storage'; diff --git a/composer.json b/composer.json index dbc80246d6..be53cb0540 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.10.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.5-rc1", + "utopia-php/database": "0.53.5", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index ea0eb28459..7611fb7032 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aeb95e5148f792325e4a96dd246118d2", + "content-hash": "1981099f3c47f5536298222ba9b0b994", "packages": [ { "name": "adhocore/jwt", @@ -1723,7 +1723,7 @@ }, { "name": "utopia-php/database", - "version": "0.53.5-rc1", + "version": "0.53.5", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", @@ -1773,7 +1773,7 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.5-rc1" + "source": "https://github.com/utopia-php/database/tree/0.53.5" }, "time": "2024-09-24T08:43:10+00:00" }, @@ -6995,9 +6995,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 5 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 36b246b28b..d8f1d7da09 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -50,6 +50,7 @@ class Mapper $defaults = [ 'boolean' => Type::boolean(), 'string' => Type::string(), + 'payload' => Type::string(), 'integer' => Type::int(), 'double' => Type::float(), 'datetime' => Type::string(), diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index b0f05522fa..510fec0431 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -489,11 +489,29 @@ class Messaging extends Action return match ($provider->getAttribute('provider')) { 'mock' => new Mock('username', 'password'), - 'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken'], null, isset($credentials['messagingServiceSid']) ? $credentials['messagingServiceSid'] : null), - 'textmagic' => new TextMagic($credentials['username'], $credentials['apiKey']), - 'telesign' => new Telesign($credentials['customerId'], $credentials['apiKey']), - 'msg91' => new Msg91($credentials['senderId'], $credentials['authKey'], $credentials['templateId']), - 'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']), + 'twilio' => new Twilio( + $credentials['accountSid'] ?? '', + $credentials['authToken'] ?? '', + null, + $credentials['messagingServiceSid'] ?? null + ), + 'textmagic' => new TextMagic( + $credentials['username'] ?? '', + $credentials['apiKey'] ?? '' + ), + 'telesign' => new Telesign( + $credentials['customerId'] ?? '', + $credentials['apiKey'] ?? '' + ), + 'msg91' => new Msg91( + $credentials['senderId'] ?? '', + $credentials['authKey'] ?? '', + $credentials['templateId'] ?? '' + ), + 'vonage' => new Vonage( + $credentials['apiKey'] ?? '', + $credentials['apiSecret'] ?? '' + ), default => null }; } @@ -506,11 +524,11 @@ class Messaging extends Action return match ($provider->getAttribute('provider')) { 'mock' => new Mock('username', 'password'), 'apns' => new APNS( - $credentials['authKey'], - $credentials['authKeyId'], - $credentials['teamId'], - $credentials['bundleId'], - $options['sandbox'] + $credentials['authKey'] ?? '', + $credentials['authKeyId'] ?? '', + $credentials['teamId'] ?? '', + $credentials['bundleId'] ?? '', + $options['sandbox'] ?? false ), 'fcm' => new FCM(\json_encode($credentials['serviceAccountJSON'])), default => null @@ -521,24 +539,25 @@ class Messaging extends Action { $credentials = $provider->getAttribute('credentials', []); $options = $provider->getAttribute('options', []); + $apiKey = $credentials['apiKey'] ?? ''; return match ($provider->getAttribute('provider')) { 'mock' => new Mock('username', 'password'), 'smtp' => new SMTP( - $credentials['host'], - $credentials['port'], - $credentials['username'], - $credentials['password'], - $options['encryption'], - $options['autoTLS'], - $options['mailer'], + $credentials['host'] ?? '', + $credentials['port'] ?? 25, + $credentials['username'] ?? '', + $credentials['password'] ?? '', + $options['encryption'] ?? '', + $options['autoTLS'] ?? false, + $options['mailer'] ?? '', ), 'mailgun' => new Mailgun( - $credentials['apiKey'], - $credentials['domain'], - $credentials['isEuRegion'] + $apiKey, + $credentials['domain'] ?? '', + $credentials['isEuRegion'] ?? false ), - 'sendgrid' => new Sendgrid($credentials['apiKey']), + 'sendgrid' => new Sendgrid($apiKey), default => null }; } diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index e5d05bb2fb..b5480e1dec 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -163,7 +163,6 @@ class UsageDump extends Action $id = \md5("{$time}_{$period}_{$key}"); $value = 0; - $diskValue = 0; $previousValue = 0; try { $previousValue = ($dbForProject->getDocument('stats', $id))->getAttribute('value', 0); @@ -179,8 +178,7 @@ class UsageDump extends Action $collectionInternalId = $data[1]; try { - $value = $dbForProject->getSizeOfCollection('database_'.$databaseInternalId.'_collection_'.$collectionInternalId); - $diskValue = $dbForProject->getSizeOfCollectionOnDisk('database_'.$databaseInternalId.'_collection_'.$collectionInternalId); + $value = $dbForProject->getSizeOfCollection('database_' . $databaseInternalId . '_collection_' . $collectionInternalId); } catch (\Exception $e) { // Collection not found if ($e->getMessage() !== 'Collection not found') { @@ -190,25 +188,21 @@ class UsageDump extends Action // Compare with previous value $diff = $value - $previousValue; - $diskDiff = $diskValue - $previousValue; - if ($diff === 0 && $diskDiff === 0) { + if ($diff === 0) { break; } // Update Collection $updateMetric($dbForProject, $diff, $key, $period, $time); - $updateMetric($dbForProject, $diskDiff, $key . '_disk', $period, $time); // Update Database $databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE); $updateMetric($dbForProject, $diff, $databaseKey, $period, $time); - $updateMetric($dbForProject, $diskDiff, $databaseKey . '_disk', $period, $time); // Update Project $projectKey = METRIC_DATABASES_STORAGE; $updateMetric($dbForProject, $diff, $projectKey, $period, $time); - $updateMetric($dbForProject, $diskDiff, $projectKey . '_disk', $period, $time); break; // Database Level case METRIC_DATABASE_LEVEL_STORAGE: @@ -227,8 +221,7 @@ class UsageDump extends Action foreach ($collections as $collection) { try { - $value += $dbForProject->getSizeOfCollection('database_'.$databaseInternalId.'_collection_'.$collection->getInternalId()); - $diskValue += $dbForProject->getSizeOfCollectionOnDisk('database_'.$databaseInternalId.'_collection_'.$collection->getInternalId()); + $value += $dbForProject->getSizeOfCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); } catch (\Exception $e) { // Collection not found if ($e->getMessage() !== 'Collection not found') { @@ -238,21 +231,18 @@ class UsageDump extends Action } $diff = $value - $previousValue; - $diskDiff = $diskValue - $previousValue; - if ($diff === 0 && $diskDiff === 0) { + if ($diff === 0) { break; } // Update Database $databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE); $updateMetric($dbForProject, $diff, $databaseKey, $period, $time); - $updateMetric($dbForProject, $diskDiff, $databaseKey . '_disk', $period, $time); // Update Project $projectKey = METRIC_DATABASES_STORAGE; $updateMetric($dbForProject, $diff, $projectKey, $period, $time); - $updateMetric($dbForProject, $diskDiff, $projectKey . '_disk', $period, $time); break; // Project Level case METRIC_PROJECT_LEVEL_STORAGE: @@ -266,8 +256,7 @@ class UsageDump extends Action foreach ($collections as $collection) { try { - $value += $dbForProject->getSizeOfCollection('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); - $diskValue += $dbForProject->getSizeOfCollectionOnDisk('database_'.$database->getInternalId().'_collection_'.$collection->getInternalId()); + $value += $dbForProject->getSizeOfCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); } catch (\Exception $e) { // Collection not found if ($e->getMessage() !== 'Collection not found') { @@ -278,12 +267,10 @@ class UsageDump extends Action } $diff = $value - $previousValue; - $diskDiff = $diskValue - $previousValue; // Update Project $projectKey = METRIC_DATABASES_STORAGE; $updateMetric($dbForProject, $diff, $projectKey, $period, $time); - $updateMetric($dbForProject, $diskDiff, $projectKey . '_disk', $period, $time); break; } } diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 3074d59b7c..f7430ec70e 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -549,6 +549,7 @@ class OpenAPI3 extends Format switch ($rule['type']) { case 'string': case 'datetime': + case 'payload': $type = 'string'; break; diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 2eab7807b3..0dac729358 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -585,6 +585,10 @@ class Swagger2 extends Format $type = 'boolean'; break; + case 'payload': + $type = 'payload'; + break; + default: $type = 'object'; $rule['type'] = ($rule['type']) ?: 'none'; diff --git a/src/Appwrite/Utopia/Response/Model.php b/src/Appwrite/Utopia/Response/Model.php index 8a0bb78cba..d14d1be0c1 100644 --- a/src/Appwrite/Utopia/Response/Model.php +++ b/src/Appwrite/Utopia/Response/Model.php @@ -14,6 +14,7 @@ abstract class Model public const TYPE_DATETIME = 'datetime'; public const TYPE_DATETIME_EXAMPLE = '2020-10-15T06:38:00.000+00:00'; public const TYPE_RELATIONSHIP = 'relationship'; + public const TYPE_PAYLOAD = 'payload'; /** * @var bool diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index 90fbdc9689..dc5d41c02c 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -81,10 +81,9 @@ class Execution extends Model 'example' => 200, ]) ->addRule('responseBody', [ - 'type' => self::TYPE_STRING, + 'type' => self::TYPE_PAYLOAD, 'description' => 'HTTP response body. This will return empty unless execution is created as synchronous.', 'default' => '', - 'example' => 'Developers are awesome.', ]) ->addRule('responseHeaders', [ 'type' => Response::MODEL_HEADERS, diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 0881966365..fe600cd0f8 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -133,7 +133,7 @@ class HTTPTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); // looks like recent change in the validator - $this->assertTrue(empty($response['body']['schemaValidationMessages'])); + $this->assertEmpty($response['body']['schemaValidationMessages'], 'Schema validation failed for ' . $file . ': ' . json_encode($response['body']['schemaValidationMessages'], JSON_PRETTY_PRINT)); } }