diff --git a/app/config/locale/translations/tr.json b/app/config/locale/translations/tr.json index 6a94aeacae..e82317de01 100644 --- a/app/config/locale/translations/tr.json +++ b/app/config/locale/translations/tr.json @@ -3,30 +3,36 @@ "settings.locale": "tr", "settings.direction": "ltr", "emails.sender": "%s Takımı", - "emails.verification.subject": "", - "emails.verification.hello": "", - "emails.verification.body": "", - "emails.verification.footer": "", - "emails.verification.thanks": "", - "emails.verification.signature": "", - "emails.magicSession.subject": "", - "emails.magicSession.hello": "", - "emails.magicSession.body": "", - "emails.magicSession.footer": "", - "emails.magicSession.thanks": "", - "emails.magicSession.signature": "", - "emails.recovery.subject": "", - "emails.recovery.hello": "", - "emails.recovery.body": "", - "emails.recovery.footer": "", - "emails.recovery.thanks": "", - "emails.recovery.signature": "", - "emails.invitation.subject": "", - "emails.invitation.hello": "", - "emails.invitation.body": "", - "emails.invitation.footer": "", - "emails.invitation.thanks": "", - "emails.invitation.signature": "", + "emails.verification.subject": "Hesabını Doğrula", + "emails.verification.hello": "Merhaba {{user}}", + "emails.verification.body": "Eposta adresini doğrulamak için bu bağlantıyı kullanın.", + "emails.verification.footer": "Eğer bu eposta adresini doğrulamak isteyen siz değilseniz devam etmeyin.", + "emails.verification.thanks": "Teşekkürler", + "emails.verification.signature": "{{project}} takımı", + "emails.magicSession.subject": "Giriş", + "emails.magicSession.hello": "Merhaba,", + "emails.magicSession.body": "Giriş yapmak için tıklayın.", + "emails.magicSession.footer": "Eğer bu eposta adresini kullanarak giriş yapmak istemediyseniz devam etmeyin.", + "emails.magicSession.thanks": "Teşekkürler", + "emails.magicSession.signature": "{{project}} takımı", + "emails.recovery.subject": "Şifremi Sıfırla", + "emails.recovery.hello": "Merhaba {{user}}", + "emails.recovery.body": "{{project}} şifrenizi sıfırlamak için bu bağlantıyı kullanın.", + "emails.recovery.footer": "Eğer şifre sıfırlama talebinde bulunmadıysanız devam etmeyin.", + "emails.recovery.thanks": "Teşekkürler", + "emails.recovery.signature": "{{project}} takımı", + "emails.invitation.subject": "%s üzerinde %s Takımına Davet", + "emails.invitation.hello": "Merhaba", + "emails.invitation.body": "Bu epostayı aldınız, çünkü {{owner}} sizi {{project}} üzerinde {{team}} takımının üyesi olmaya davet etti.", + "emails.invitation.footer": "Eğer ilgilenmiyorsanız devam etmeyin.", + "emails.invitation.thanks": "Teşekkürler", + "emails.invitation.signature": "{{project}} takımı", + "emails.certificate.subject": "%s için sertifika hatası", + "emails.certificate.hello": "Merhaba", + "emails.certificate.body": "Alan adınız '{{domain}}' için sertifika oluşturulamadı. Deneme sayısı {{attempt}} ve hata sebebi: {{error}}", + "emails.certificate.footer": "Geçmiş sertifikanız ilk denemeden sonra 30 gün daha geçerli kalacaktır. Bu konuyu araştırmanızı öneriyoruz, aksi taktirde alan adınız SSL sertifikasız kalacaktır.", + "emails.certificate.thanks": "Teşekkürler", + "emails.certificate.signature": "{{project}} takımı", "locale.country.unknown": "Bilinmeyen", "countries.af": "Afganistan", "countries.ao": "Angola", @@ -229,4 +235,4 @@ "continents.na": "Kuzey Amerika", "continents.oc": "Okyanusya", "continents.sa": "Güney Amerika" -} \ No newline at end of file +} diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index c210b19f4f..54967fb502 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -550,11 +550,19 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if (!$user->isEmpty()) { $userId = $user->getId(); - $identitiesWithMatchingEmail = $dbForProject->find('identities', [ + $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), Query::notEqual('userId', $userId), ]); - if (!empty($identitiesWithMatchingEmail)) { + if (!empty($identityWithMatchingEmail)) { + throw new Exception(Exception::USER_ALREADY_EXISTS); + } + + $userWithMatchingEmail = $dbForProject->find('users', [ + Query::equal('email', [$email]), + Query::notEqual('$id', $userId), + ]); + if (!empty($userWithMatchingEmail)) { throw new Exception(Exception::USER_ALREADY_EXISTS); } } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 687971c2d0..e668ec2552 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -44,6 +44,7 @@ use Utopia\Validator\Text; use Utopia\Validator\WhiteList; use Utopia\DSN\DSN; use Utopia\Swoole\Request; +use Utopia\Storage\Compression\Compression; App::post('/v1/storage/buckets') ->desc('Create bucket') @@ -67,7 +68,7 @@ App::post('/v1/storage/buckets') ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') @@ -241,7 +242,7 @@ App::put('/v1/storage/buckets/:bucketId') ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') @@ -538,19 +539,24 @@ App::post('/v1/storage/buckets/:bucketId/files') $fileHash = $deviceFiles->getFileHash($path); // Get file hash before compression and encryption $data = ''; // Compression - $algorithm = $bucket->getAttribute('compression', COMPRESSION_TYPE_NONE); - if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != COMPRESSION_TYPE_NONE) { + $algorithm = $bucket->getAttribute('compression', Compression::NONE); + if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != Compression::NONE) { $data = $deviceFiles->read($path); switch ($algorithm) { - case COMPRESSION_TYPE_ZSTD: + case Compression::ZSTD: $compressor = new Zstd(); break; - case COMPRESSION_TYPE_GZIP: + case Compression::GZIP: default: $compressor = new GZIP(); break; } $data = $compressor->compress($data); + } else { + // reset the algorithm to none as we do not compress the file + // if file size exceedes the APP_STORAGE_READ_BUFFER + // regardless the bucket compression algoorithm + $algorithm = Compression::NONE; } if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) { @@ -882,14 +888,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception(Exception::USER_UNAUTHORIZED); } - 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'); - if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { @@ -900,9 +898,17 @@ 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'); + $path = $file->getAttribute('path'); $type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION)); - $algorithm = $file->getAttribute('algorithm', 'none'); + $algorithm = $file->getAttribute('algorithm', Compression::NONE); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { @@ -913,7 +919,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $path = $fileLogos['default_image']; } - $algorithm = 'none'; + $algorithm = Compression::NONE; $cipher = null; $background = (empty($background)) ? 'eceff1' : $background; $type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION)); @@ -925,12 +931,17 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } if (empty($output)) { + // when file extension is provided but it's not one of our + // supported outputs we fallback to `jpg` + if (!empty($type) && !array_key_exists($type, $outputs)) { + $type = 'jpg'; + } + // when file extension is not provided and the mime type is not one of our supported outputs // we fallback to `jpg` output format $output = empty($type) ? (array_search($mime, $outputs) ?? 'jpg') : $type; } - $source = $deviceFiles->read($path); if (!empty($cipher)) { // Decrypt @@ -945,11 +956,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } switch ($algorithm) { - case 'zstd': + case Compression::ZSTD: $compressor = new Zstd(); $source = $compressor->decompress($source); break; - case 'gzip': + case Compression::GZIP: $compressor = new GZIP(); $source = $compressor->decompress($source); break; @@ -1090,15 +1101,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ); } - switch ($file->getAttribute('algorithm', 'none')) { - case 'zstd': + switch ($file->getAttribute('algorithm', Compression::NONE)) { + case Compression::ZSTD: if (empty($source)) { $source = $deviceFiles->read($path); } $compressor = new Zstd(); $source = $compressor->decompress($source); break; - case 'gzip': + case Compression::GZIP: if (empty($source)) { $source = $deviceFiles->read($path); } @@ -1241,15 +1252,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ); } - switch ($file->getAttribute('algorithm', 'none')) { - case 'zstd': + switch ($file->getAttribute('algorithm', Compression::NONE)) { + case Compression::ZSTD: if (empty($source)) { $source = $deviceFiles->read($path); } $compressor = new Zstd(); $source = $compressor->decompress($source); break; - case 'gzip': + case Compression::GZIP: if (empty($source)) { $source = $deviceFiles->read($path); } @@ -1263,10 +1274,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); + return; } if (!empty($rangeHeader)) { $response->send($deviceFiles->read($path, $start, ($end - $start + 1))); + return; } $size = $deviceFiles->getFileSize($path); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 4ea122e3c5..05cfddd276 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -556,6 +556,22 @@ App::shutdown() ->setParam('project.{scope}.network.outbound', $response->getSize()) ->submit(); } + + /** + * Update user last activity + */ + if (!$user->isEmpty()) { + $accessedAt = $user->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCCESS)) > $accessedAt) { + $user->setAttribute('accessedAt', DateTime::now()); + + if (APP_MODE_ADMIN !== $mode) { + $dbForProject->updateDocument('users', $user->getId(), $user); + } else { + $dbForConsole->updateDocument('users', $user->getId(), $user); + } + } + } }); App::init() diff --git a/app/init.php b/app/init.php index 72bf75d41b..924122ac20 100644 --- a/app/init.php +++ b/app/init.php @@ -173,10 +173,6 @@ const DELETE_TYPE_SESSIONS = 'sessions'; const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp'; const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; const DELETE_TYPE_SCHEDULES = 'schedules'; -// Compression type -const COMPRESSION_TYPE_NONE = 'none'; -const COMPRESSION_TYPE_GZIP = 'gzip'; -const COMPRESSION_TYPE_ZSTD = 'zstd'; // Mail Types const MAIL_TYPE_VERIFICATION = 'verification'; const MAIL_TYPE_MAGIC_SESSION = 'magicSession'; diff --git a/composer.lock b/composer.lock index 3518396665..acd65d61a1 100644 --- a/composer.lock +++ b/composer.lock @@ -1906,16 +1906,16 @@ }, { "name": "utopia-php/database", - "version": "0.45.2", + "version": "0.45.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "dc789f2c1fd8b5ee07ff883e11c9ad7970824788" + "reference": "33b4e9a4a6c29f6bb7e108e134b283d585955789" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/dc789f2c1fd8b5ee07ff883e11c9ad7970824788", - "reference": "dc789f2c1fd8b5ee07ff883e11c9ad7970824788", + "url": "https://api.github.com/repos/utopia-php/database/zipball/33b4e9a4a6c29f6bb7e108e134b283d585955789", + "reference": "33b4e9a4a6c29f6bb7e108e134b283d585955789", "shasum": "" }, "require": { @@ -1956,9 +1956,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.45.2" + "source": "https://github.com/utopia-php/database/tree/0.45.3" }, - "time": "2023-11-15T03:38:47+00:00" + "time": "2023-12-28T11:12:26+00:00" }, { "name": "utopia-php/domains", @@ -2476,16 +2476,16 @@ }, { "name": "utopia-php/platform", - "version": "0.5.0", + "version": "0.5.1", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "229a7b1fa1f39afd1532f7a515326a6afc222a26" + "reference": "3eceef0b6593fe0f7d2efd36d40402a395a4c285" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/229a7b1fa1f39afd1532f7a515326a6afc222a26", - "reference": "229a7b1fa1f39afd1532f7a515326a6afc222a26", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/3eceef0b6593fe0f7d2efd36d40402a395a4c285", + "reference": "3eceef0b6593fe0f7d2efd36d40402a395a4c285", "shasum": "" }, "require": { @@ -2493,7 +2493,7 @@ "ext-redis": "*", "php": ">=8.0", "utopia-php/cli": "0.15.*", - "utopia-php/framework": "0.31.*" + "utopia-php/framework": "0.*.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2519,9 +2519,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.5.0" + "source": "https://github.com/utopia-php/platform/tree/0.5.1" }, - "time": "2023-10-16T20:28:49+00:00" + "time": "2023-12-26T16:14:41+00:00" }, { "name": "utopia-php/pools", @@ -2742,16 +2742,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.1", + "version": "0.18.3", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "983e6dee137012f9f57f126d3c79aab54e4e8824" + "reference": "faa0279519ac14f3501e8b138e0865ad9d12bff6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/983e6dee137012f9f57f126d3c79aab54e4e8824", - "reference": "983e6dee137012f9f57f126d3c79aab54e4e8824", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/faa0279519ac14f3501e8b138e0865ad9d12bff6", + "reference": "faa0279519ac14f3501e8b138e0865ad9d12bff6", "shasum": "" }, "require": { @@ -2791,9 +2791,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.1" + "source": "https://github.com/utopia-php/storage/tree/0.18.3" }, - "time": "2023-10-24T14:44:19+00:00" + "time": "2023-12-31T11:45:12+00:00" }, { "name": "utopia-php/swoole", @@ -2904,23 +2904,23 @@ }, { "name": "utopia-php/vcs", - "version": "0.6.2", + "version": "0.6.4", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "f135291b87cb45335fc6608722e7f89894bc33ee" + "reference": "b2595a50a4897a8c88319240810055b7a96efd6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/f135291b87cb45335fc6608722e7f89894bc33ee", - "reference": "f135291b87cb45335fc6608722e7f89894bc33ee", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/b2595a50a4897a8c88319240810055b7a96efd6d", + "reference": "b2595a50a4897a8c88319240810055b7a96efd6d", "shasum": "" }, "require": { "adhocore/jwt": "^1.1", "php": ">=8.0", "utopia-php/cache": "^0.8.0", - "utopia-php/framework": "0.31.*" + "utopia-php/framework": "0.*.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2947,9 +2947,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.6.2" + "source": "https://github.com/utopia-php/vcs/tree/0.6.4" }, - "time": "2023-11-08T15:36:03+00:00" + "time": "2023-12-26T15:38:19+00:00" }, { "name": "utopia-php/websocket", @@ -3487,16 +3487,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -3537,9 +3537,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "phar-io/manifest", @@ -3891,16 +3891,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.4", + "version": "1.24.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496" + "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6bd0c26f3786cd9b7c359675cb789e35a8e07496", - "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc", + "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc", "shasum": "" }, "require": { @@ -3932,29 +3932,29 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.4" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5" }, - "time": "2023-11-26T18:29:22+00:00" + "time": "2023-12-16T09:33:33+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.29", + "version": "9.2.30", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -4004,7 +4004,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" }, "funding": [ { @@ -4012,7 +4012,7 @@ "type": "github" } ], - "time": "2023-09-19T04:57:46+00:00" + "time": "2023-12-22T06:47:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -4651,20 +4651,20 @@ }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -4696,7 +4696,7 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" }, "funding": [ { @@ -4704,7 +4704,7 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { "name": "sebastian/diff", @@ -4978,20 +4978,20 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -5023,7 +5023,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" }, "funding": [ { @@ -5031,7 +5031,7 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { "name": "sebastian/object-enumerator", diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index 3c5715efc2..f5261c026e 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Storage\Compression\Compression; class Bucket extends Model { @@ -68,7 +69,7 @@ class Bucket extends Model ]) ->addRule('compression', [ 'type' => self::TYPE_STRING, - 'description' => 'Compression algorithm choosen for compression. Will be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd).', + 'description' => 'Compression algorithm choosen for compression. Will be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd).', 'default' => '', 'example' => 'gzip', 'array' => false diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index eb6a52db6b..c4a15585eb 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -27,7 +27,7 @@ trait StorageBase 'name' => 'Test Bucket', 'fileSecurity' => true, 'maximumFileSize' => 2000000, //2MB - 'allowedFileExtensions' => ["jpg", "png"], + 'allowedFileExtensions' => ["jpg", "png", 'jfif'], 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -457,6 +457,32 @@ trait StorageBase $this->assertEquals('image/png', $file2['headers']['content-type']); $this->assertNotEmpty($file2['body']); + // upload JXL file for preview + $fileJfif = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-a/preview-test.jfif'), 'image/jxl', 'preview-test.jfif'), + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + $this->assertEquals(201, $fileJfif['headers']['status-code']); + $this->assertNotEmpty($fileJfif['body']['$id']); + + // TEST preview JXL + $preview = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileJfif['body']['$id'] . '/preview', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $preview['headers']['status-code']); + $this->assertEquals('image/jpeg', $preview['headers']['content-type']); + $this->assertNotEmpty($preview['body']); + //new image preview features $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/preview', array_merge([ 'content-type' => 'application/json', diff --git a/tests/resources/disk-a/preview-test.jfif b/tests/resources/disk-a/preview-test.jfif new file mode 100644 index 0000000000..e50021f95d Binary files /dev/null and b/tests/resources/disk-a/preview-test.jfif differ