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/config/storage/mimes.php b/app/config/storage/mimes.php index 5d315f45bc..df325b37e9 100644 --- a/app/config/storage/mimes.php +++ b/app/config/storage/mimes.php @@ -6,6 +6,8 @@ return [ 'image/gif', 'image/png', 'image/webp', + // 'image/heic', + 'image/avif', // Video Files 'video/mp4', diff --git a/app/config/storage/outputs.php b/app/config/storage/outputs.php index 507a9ce667..cde2a9f38a 100644 --- a/app/config/storage/outputs.php +++ b/app/config/storage/outputs.php @@ -6,4 +6,7 @@ return [ // Accepted outputs files 'gif' => 'image/gif', 'png' => 'image/png', 'webp' => 'image/webp', + // 'heic' => 'image/heic', + // 'heics' => 'image/heic', + 'avif' => 'image/avif' ]; diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index ca248c2628..4e30832a67 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -889,10 +889,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } - if ((\strpos($request->getAccept(), 'image/webp') === false) && ('webp' === $output)) { // Fallback webp to jpeg when no browser support - $output = 'jpg'; - } - $inputs = Config::getParam('storage-inputs'); $outputs = Config::getParam('storage-outputs'); $fileLogos = Config::getParam('storage-logos'); diff --git a/composer.json b/composer.json index be53cb0540..575973e54d 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", "utopia-php/fetch": "0.2.*", - "utopia-php/image": "0.6.*", + "utopia-php/image": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.12.*", diff --git a/composer.lock b/composer.lock index 7611fb7032..93672e670e 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": "1981099f3c47f5536298222ba9b0b994", + "content-hash": "66e31af1f7d0d1617694a1c5a975f887", "packages": [ { "name": "adhocore/jwt", @@ -1970,21 +1970,21 @@ }, { "name": "utopia-php/image", - "version": "0.6.1", + "version": "0.7.0", "source": { "type": "git", "url": "https://github.com/utopia-php/image.git", - "reference": "2d74c27e69e65a93cf94a16586598a04fe435bf0" + "reference": "fcea143edbad524bf871ddbebe801d981f91f181" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/image/zipball/2d74c27e69e65a93cf94a16586598a04fe435bf0", - "reference": "2d74c27e69e65a93cf94a16586598a04fe435bf0", + "url": "https://api.github.com/repos/utopia-php/image/zipball/fcea143edbad524bf871ddbebe801d981f91f181", + "reference": "fcea143edbad524bf871ddbebe801d981f91f181", "shasum": "" }, "require": { "ext-imagick": "*", - "php": ">=8.0" + "php": ">=8.1" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2012,9 +2012,9 @@ ], "support": { "issues": "https://github.com/utopia-php/image/issues", - "source": "https://github.com/utopia-php/image/tree/0.6.1" + "source": "https://github.com/utopia-php/image/tree/0.7.0" }, - "time": "2024-02-05T13:31:44+00:00" + "time": "2024-10-02T05:45:38+00:00" }, { "name": "utopia-php/locale", 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/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)); } }