Merge remote-tracking branch 'origin/0.16.x' into fix-ui-with-queries-v2
This commit is contained in:
commit
a85a471d3b
19 changed files with 246 additions and 61 deletions
18
Dockerfile
18
Dockerfile
|
@ -34,7 +34,8 @@ ENV PHP_REDIS_VERSION=5.3.7 \
|
||||||
PHP_SWOOLE_VERSION=v4.8.10 \
|
PHP_SWOOLE_VERSION=v4.8.10 \
|
||||||
PHP_IMAGICK_VERSION=3.7.0 \
|
PHP_IMAGICK_VERSION=3.7.0 \
|
||||||
PHP_YAML_VERSION=2.2.2 \
|
PHP_YAML_VERSION=2.2.2 \
|
||||||
PHP_MAXMINDDB_VERSION=v1.11.0
|
PHP_MAXMINDDB_VERSION=v1.11.0 \
|
||||||
|
PHP_ZSTD_VERSION="4504e4186e79b197cfcb75d4d09aa47ef7d92fe9 "
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk add --no-cache --virtual .deps \
|
apk add --no-cache --virtual .deps \
|
||||||
|
@ -50,7 +51,8 @@ RUN \
|
||||||
yaml-dev \
|
yaml-dev \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
imagemagick-dev \
|
imagemagick-dev \
|
||||||
libmaxminddb-dev
|
libmaxminddb-dev \
|
||||||
|
zstd-dev
|
||||||
|
|
||||||
RUN docker-php-ext-install sockets
|
RUN docker-php-ext-install sockets
|
||||||
|
|
||||||
|
@ -123,6 +125,16 @@ RUN \
|
||||||
./configure && \
|
./configure && \
|
||||||
make && make install
|
make && make install
|
||||||
|
|
||||||
|
# Zstd Compression
|
||||||
|
FROM compile as zstd
|
||||||
|
RUN git clone --recursive -n https://github.com/kjdev/php-ext-zstd.git \
|
||||||
|
&& cd php-ext-zstd \
|
||||||
|
&& git checkout $PHP_ZSTD_VERSION \
|
||||||
|
&& phpize \
|
||||||
|
&& ./configure --with-libzstd \
|
||||||
|
&& make && make install
|
||||||
|
|
||||||
|
|
||||||
# Rust Extensions Compile Image
|
# Rust Extensions Compile Image
|
||||||
FROM php:8.0.18-cli as rust_compile
|
FROM php:8.0.18-cli as rust_compile
|
||||||
|
|
||||||
|
@ -293,6 +305,7 @@ COPY --from=yaml /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so
|
||||||
COPY --from=maxmind /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
COPY --from=maxmind /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||||
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20200930/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20200930/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||||
COPY --from=scrypt /usr/local/lib/php/extensions/php-scrypt/target/libphp_scrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
COPY --from=scrypt /usr/local/lib/php/extensions/php-scrypt/target/libphp_scrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||||
|
COPY --from=zstd /usr/local/lib/php/extensions/no-debug-non-zts-20200930/zstd.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||||
|
|
||||||
# Add Source Code
|
# Add Source Code
|
||||||
COPY ./app /usr/src/code/app
|
COPY ./app /usr/src/code/app
|
||||||
|
@ -350,6 +363,7 @@ RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini
|
||||||
RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini
|
RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini
|
||||||
RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini
|
RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini
|
||||||
RUN echo extension=libphp_scrypt.so >> /usr/local/etc/php/conf.d/libphp_scrypt.ini
|
RUN echo extension=libphp_scrypt.so >> /usr/local/etc/php/conf.d/libphp_scrypt.ini
|
||||||
|
RUN echo extension=zstd.so >> /usr/local/etc/php/conf.d/zstd.ini
|
||||||
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
||||||
|
|
||||||
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
||||||
|
|
|
@ -2882,6 +2882,16 @@ $collections = [
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'array' => true,
|
'array' => true,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'$id' => 'compression',
|
||||||
|
'type' => Database::VAR_STRING,
|
||||||
|
'signed' => true,
|
||||||
|
'size' => 10,
|
||||||
|
'format' => '',
|
||||||
|
'filters' => [],
|
||||||
|
'required' => true,
|
||||||
|
'array' => false,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'$id' => ID::custom('encryption'),
|
'$id' => ID::custom('encryption'),
|
||||||
'type' => Database::VAR_BOOLEAN,
|
'type' => Database::VAR_BOOLEAN,
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -6,7 +6,6 @@ use Appwrite\Event\Delete;
|
||||||
use Appwrite\Event\Event;
|
use Appwrite\Event\Event;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
use Appwrite\Usage\Stats;
|
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
@ -29,8 +28,8 @@ use Appwrite\Utopia\Database\Validator\Queries\Buckets;
|
||||||
use Appwrite\Utopia\Database\Validator\Queries\Files;
|
use Appwrite\Utopia\Database\Validator\Queries\Files;
|
||||||
use Utopia\Image\Image;
|
use Utopia\Image\Image;
|
||||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||||
|
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||||
use Utopia\Storage\Device;
|
use Utopia\Storage\Device;
|
||||||
use Utopia\Storage\Device\Local;
|
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Storage;
|
||||||
use Utopia\Storage\Validator\File;
|
use Utopia\Storage\Validator\File;
|
||||||
use Utopia\Storage\Validator\FileExt;
|
use Utopia\Storage\Validator\FileExt;
|
||||||
|
@ -39,7 +38,6 @@ use Utopia\Storage\Validator\Upload;
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\HexColor;
|
use Utopia\Validator\HexColor;
|
||||||
use Utopia\Validator\Integer;
|
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
@ -66,12 +64,13 @@ App::post('/v1/storage/buckets')
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', 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) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', 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) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', 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('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', '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('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('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)
|
->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')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('events')
|
->inject('events')
|
||||||
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
|
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
|
||||||
|
|
||||||
$bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId;
|
$bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId;
|
||||||
|
|
||||||
|
@ -120,6 +119,7 @@ App::post('/v1/storage/buckets')
|
||||||
'allowedFileExtensions' => $allowedFileExtensions,
|
'allowedFileExtensions' => $allowedFileExtensions,
|
||||||
'fileSecurity' => $fileSecurity,
|
'fileSecurity' => $fileSecurity,
|
||||||
'enabled' => $enabled,
|
'enabled' => $enabled,
|
||||||
|
'compression' => $compression,
|
||||||
'encryption' => $encryption,
|
'encryption' => $encryption,
|
||||||
'antivirus' => $antivirus,
|
'antivirus' => $antivirus,
|
||||||
'search' => implode(' ', [$bucketId, $name]),
|
'search' => implode(' ', [$bucketId, $name]),
|
||||||
|
@ -234,12 +234,13 @@ App::put('/v1/storage/buckets/:bucketId')
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', 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) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', 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) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', 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('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', '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('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('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)
|
->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')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('events')
|
->inject('events')
|
||||||
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
|
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
|
||||||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||||
|
|
||||||
if ($bucket->isEmpty()) {
|
if ($bucket->isEmpty()) {
|
||||||
|
@ -268,6 +269,7 @@ App::put('/v1/storage/buckets/:bucketId')
|
||||||
->setAttribute('fileSecurity', $fileSecurity)
|
->setAttribute('fileSecurity', $fileSecurity)
|
||||||
->setAttribute('enabled', $enabled)
|
->setAttribute('enabled', $enabled)
|
||||||
->setAttribute('encryption', $encryption)
|
->setAttribute('encryption', $encryption)
|
||||||
|
->setAttribute('compression', $compression)
|
||||||
->setAttribute('antivirus', $antivirus));
|
->setAttribute('antivirus', $antivirus));
|
||||||
|
|
||||||
$events
|
$events
|
||||||
|
@ -502,9 +504,18 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
||||||
$data = '';
|
$data = '';
|
||||||
// Compression
|
// Compression
|
||||||
if ($fileSize <= APP_STORAGE_READ_BUFFER) {
|
$algorithm = $bucket->getAttribute('compression', 'none');
|
||||||
|
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != 'none') {
|
||||||
$data = $deviceFiles->read($path);
|
$data = $deviceFiles->read($path);
|
||||||
|
switch ($algorithm) {
|
||||||
|
case 'zstd':
|
||||||
|
$compressor = new Zstd();
|
||||||
|
break;
|
||||||
|
case 'gzip':
|
||||||
|
default:
|
||||||
$compressor = new GZIP();
|
$compressor = new GZIP();
|
||||||
|
break;
|
||||||
|
}
|
||||||
$data = $compressor->compress($data);
|
$data = $compressor->compress($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,8 +535,6 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
}
|
}
|
||||||
|
|
||||||
$sizeActual = $deviceFiles->getFileSize($path);
|
$sizeActual = $deviceFiles->getFileSize($path);
|
||||||
|
|
||||||
$algorithm = empty($compressor) ? '' : $compressor->getName();
|
|
||||||
$fileHash = $deviceFiles->getFileHash($path);
|
$fileHash = $deviceFiles->getFileHash($path);
|
||||||
|
|
||||||
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
|
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
|
||||||
|
@ -840,7 +849,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
||||||
|
|
||||||
$path = $file->getAttribute('path');
|
$path = $file->getAttribute('path');
|
||||||
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
||||||
$algorithm = $file->getAttribute('algorithm');
|
$algorithm = $file->getAttribute('algorithm', 'none');
|
||||||
$cipher = $file->getAttribute('openSSLCipher');
|
$cipher = $file->getAttribute('openSSLCipher');
|
||||||
$mime = $file->getAttribute('mimeType');
|
$mime = $file->getAttribute('mimeType');
|
||||||
if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) {
|
if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) {
|
||||||
|
@ -851,16 +860,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
||||||
$path = $fileLogos['default_image'];
|
$path = $fileLogos['default_image'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$algorithm = null;
|
$algorithm = 'none';
|
||||||
$cipher = null;
|
$cipher = null;
|
||||||
$background = (empty($background)) ? 'eceff1' : $background;
|
$background = (empty($background)) ? 'eceff1' : $background;
|
||||||
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
||||||
$deviceFiles = $deviceLocal;
|
$deviceFiles = $deviceLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$compressor = new GZIP();
|
|
||||||
|
|
||||||
if (!$deviceFiles->exists($path)) {
|
if (!$deviceFiles->exists($path)) {
|
||||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -885,8 +891,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($algorithm)) {
|
switch ($algorithm) {
|
||||||
|
case 'zstd':
|
||||||
|
$compressor = new Zstd();
|
||||||
$source = $compressor->decompress($source);
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
|
case 'gzip':
|
||||||
|
$compressor = new GZIP();
|
||||||
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$image = new Image($source);
|
$image = new Image($source);
|
||||||
|
@ -1021,12 +1034,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($file->getAttribute('algorithm', ''))) {
|
switch ($file->getAttribute('algorithm', 'none')) {
|
||||||
|
case 'zstd':
|
||||||
|
if (empty($source)) {
|
||||||
|
$source = $deviceFiles->read($path);
|
||||||
|
}
|
||||||
|
$compressor = new Zstd();
|
||||||
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
|
case 'gzip':
|
||||||
if (empty($source)) {
|
if (empty($source)) {
|
||||||
$source = $deviceFiles->read($path);
|
$source = $deviceFiles->read($path);
|
||||||
}
|
}
|
||||||
$compressor = new GZIP();
|
$compressor = new GZIP();
|
||||||
$source = $compressor->decompress($source);
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($source)) {
|
if (!empty($source)) {
|
||||||
|
@ -1162,12 +1184,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($file->getAttribute('algorithm', ''))) {
|
switch ($file->getAttribute('algorithm', 'none')) {
|
||||||
|
case 'zstd':
|
||||||
|
if (empty($source)) {
|
||||||
|
$source = $deviceFiles->read($path);
|
||||||
|
}
|
||||||
|
$compressor = new Zstd();
|
||||||
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
|
case 'gzip':
|
||||||
if (empty($source)) {
|
if (empty($source)) {
|
||||||
$source = $deviceFiles->read($path);
|
$source = $deviceFiles->read($path);
|
||||||
}
|
}
|
||||||
$compressor = new GZIP();
|
$compressor = new GZIP();
|
||||||
$source = $compressor->decompress($source);
|
$source = $compressor->decompress($source);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($source)) {
|
if (!empty($source)) {
|
||||||
|
|
|
@ -169,6 +169,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
|
||||||
'maximumFileSize' => (int) App::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
|
'maximumFileSize' => (int) App::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
|
||||||
'allowedFileExtensions' => [],
|
'allowedFileExtensions' => [],
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
|
'compression' => 'gzip',
|
||||||
'encryption' => true,
|
'encryption' => true,
|
||||||
'antivirus' => true,
|
'antivirus' => true,
|
||||||
'fileSecurity' => true,
|
'fileSecurity' => true,
|
||||||
|
|
|
@ -151,6 +151,10 @@ const DELETE_TYPE_BUCKETS = 'buckets';
|
||||||
const DELETE_TYPE_SESSIONS = 'sessions';
|
const DELETE_TYPE_SESSIONS = 'sessions';
|
||||||
const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp';
|
const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp';
|
||||||
const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource';
|
const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource';
|
||||||
|
// Compression type
|
||||||
|
const COMPRESSION_TYPE_NONE = 'none';
|
||||||
|
const COMPRESSION_TYPE_GZIP = 'gzip';
|
||||||
|
const COMPRESSION_TYPE_ZSTD = 'zstd';
|
||||||
// Mail Types
|
// Mail Types
|
||||||
const MAIL_TYPE_VERIFICATION = 'verification';
|
const MAIL_TYPE_VERIFICATION = 'verification';
|
||||||
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
|
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
|
||||||
|
|
|
@ -414,6 +414,13 @@ $fileUpdatePermissions = $this->getParam('fileUpdatePermissions', null);
|
||||||
<label for="bucket-maximum-file-size">Maximum File Size (bytes) <span class="tooltip small" data-tooltip="Limit file size allowed in the bucket."><i class="icon-info-circled"></i></span></label>
|
<label for="bucket-maximum-file-size">Maximum File Size (bytes) <span class="tooltip small" data-tooltip="Limit file size allowed in the bucket."><i class="icon-info-circled"></i></span></label>
|
||||||
<input name="maximumFileSize" id="bucket-maximum-file-size" type="number" autocomplete="off" data-ls-bind="{{project-bucket.maximumFileSize}}" min="1" data-cast-to="integer" />
|
<input name="maximumFileSize" id="bucket-maximum-file-size" type="number" autocomplete="off" data-ls-bind="{{project-bucket.maximumFileSize}}" min="1" data-cast-to="integer" />
|
||||||
|
|
||||||
|
<label for="compression">Compression</label>
|
||||||
|
<select id="compression" data-ls-bind="{{project-bucket.compression}}" name="compression">
|
||||||
|
<option value="none">None</option>
|
||||||
|
<option value="gzip">Gzip</option>
|
||||||
|
<option value="zstd">Zstd</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
<div class="margin-bottom">
|
<div class="margin-bottom">
|
||||||
<input name="enabled" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.enabled}}" /> Enabled <span class="tooltip" data-tooltip="Mark whether bucket is enabled"><i class="icon-info-circled"></i></span>
|
<input name="enabled" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.enabled}}" /> Enabled <span class="tooltip" data-tooltip="Mark whether bucket is enabled"><i class="icon-info-circled"></i></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
"utopia-php/preloader": "0.2.*",
|
"utopia-php/preloader": "0.2.*",
|
||||||
"utopia-php/domains": "1.1.*",
|
"utopia-php/domains": "1.1.*",
|
||||||
"utopia-php/swoole": "0.3.*",
|
"utopia-php/swoole": "0.3.*",
|
||||||
"utopia-php/storage": "0.9.*",
|
"utopia-php/storage": "0.11.*",
|
||||||
"utopia-php/websocket": "0.1.0",
|
"utopia-php/websocket": "0.1.0",
|
||||||
"utopia-php/image": "0.5.*",
|
"utopia-php/image": "0.5.*",
|
||||||
"utopia-php/orchestration": "0.6.*",
|
"utopia-php/orchestration": "0.6.*",
|
||||||
|
|
27
composer.lock
generated
27
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "039de21eff3a27955696a9f6f645c548",
|
"content-hash": "7c41d4bcb13c34e72039e3de7e84f732",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/jwt",
|
"name": "adhocore/jwt",
|
||||||
|
@ -2556,19 +2556,22 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/storage",
|
"name": "utopia-php/storage",
|
||||||
"version": "0.9.0",
|
"version": "0.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/storage.git",
|
"url": "https://github.com/utopia-php/storage.git",
|
||||||
"reference": "c7912481a56e17cc86358fa8de57309de5e88ef7"
|
"reference": "59802cf281d1976560cf6e353f250a9b870efddc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/c7912481a56e17cc86358fa8de57309de5e88ef7",
|
"url": "https://api.github.com/repos/utopia-php/storage/zipball/59802cf281d1976560cf6e353f250a9b870efddc",
|
||||||
"reference": "c7912481a56e17cc86358fa8de57309de5e88ef7",
|
"reference": "59802cf281d1976560cf6e353f250a9b870efddc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"ext-zlib": "*",
|
||||||
|
"ext-zstd": "*",
|
||||||
"php": ">=8.0",
|
"php": ">=8.0",
|
||||||
"utopia-php/framework": "0.*.*"
|
"utopia-php/framework": "0.*.*"
|
||||||
},
|
},
|
||||||
|
@ -2602,9 +2605,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/storage/issues",
|
"issues": "https://github.com/utopia-php/storage/issues",
|
||||||
"source": "https://github.com/utopia-php/storage/tree/0.9.0"
|
"source": "https://github.com/utopia-php/storage/tree/0.11.0"
|
||||||
},
|
},
|
||||||
"time": "2022-05-19T11:05:45+00:00"
|
"time": "2022-08-31T09:17:31+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/swoole",
|
"name": "utopia-php/swoole",
|
||||||
|
@ -2841,12 +2844,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||||
"reference": "6597948263e88f73dbdd5c70259dd54aff2dfcf8"
|
"reference": "532d4d15ec8f11539972f2848c2e230c49b24f65"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6597948263e88f73dbdd5c70259dd54aff2dfcf8",
|
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/532d4d15ec8f11539972f2848c2e230c49b24f65",
|
||||||
"reference": "6597948263e88f73dbdd5c70259dd54aff2dfcf8",
|
"reference": "532d4d15ec8f11539972f2848c2e230c49b24f65",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2883,7 +2886,7 @@
|
||||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||||
"source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers"
|
"source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers"
|
||||||
},
|
},
|
||||||
"time": "2022-08-30T18:29:13+00:00"
|
"time": "2022-08-20T07:42:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
|
@ -5383,5 +5386,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.0"
|
"php": "8.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.2.0"
|
"plugin-api-version": "2.3.0"
|
||||||
}
|
}
|
||||||
|
|
12
public/dist/scripts/app-all.js
vendored
12
public/dist/scripts/app-all.js
vendored
File diff suppressed because one or more lines are too long
10
public/dist/scripts/app-dep.js
vendored
10
public/dist/scripts/app-dep.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/scripts/app.js
vendored
2
public/dist/scripts/app.js
vendored
|
@ -522,7 +522,7 @@ return new Promise(function(resolve,reject){let request=new XMLHttpRequest(),key
|
||||||
request.onload=function(){if(4===request.readyState&&399>=request.status){let data=request.response;let contentType=this.getResponseHeader('content-type');contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;}
|
request.onload=function(){if(4===request.readyState&&399>=request.status){let data=request.response;let contentType=this.getResponseHeader('content-type');contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;}
|
||||||
resolve(data);}else{reject(new Error(request.statusText));}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);}
|
resolve(data);}else{reject(new Error(request.statusText));}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);}
|
||||||
request.onerror=function(){reject(new Error("Network Error"));};request.send(params);})};return{'get':function(path,headers={},params={}){return call('GET',path+((params.length>0)?'?'+buildQuery(params):''),headers,{});},'post':function(path,headers={},params={},progress=null){return call('POST',path,headers,params,progress);},'put':function(path,headers={},params={},progress=null){return call('PUT',headers,params,progress);},'patch':function(path,headers={},params={},progress=null){return call('PATCH',path,headers,params,progress);},'delete':function(path,headers={},params={},progress=null){return call('DELETE',path,headers,params,progress);},'addGlobalParam':addGlobalParam,'addGlobalHeader':addGlobalHeader}}(window.document);let analytics={create:function(id,source,activity,url){return http.post('/analytics',{'content-type':'application/json'},{id:id,source:source,activity:activity,url:url,version:env.VERSION,setup:env.SETUP});},};return{analytics:analytics,};},true);})(window);(function(window){"use strict";window.ls.container.set('console',function(window){var client=new Appwrite.Client();var endpoint=window.location.origin+'/v1';client.setEndpoint(endpoint).setProject('console').setLocale(APP_ENV.LOCALE);return{client:client,account:new Appwrite.Account(client),avatars:new Appwrite.Avatars(client),databases:new Appwrite.Databases(client),functions:new Appwrite.Functions(client),health:new Appwrite.Health(client),locale:new Appwrite.Locale(client),projects:new Appwrite.Projects(client),storage:new Appwrite.Storage(client),teams:new Appwrite.Teams(client),users:new Appwrite.Users(client)}},true);})(window);(function(window){"use strict";window.ls.container.set('date',function(){function format(format,datetime){if(!datetime){return null;}
|
request.onerror=function(){reject(new Error("Network Error"));};request.send(params);})};return{'get':function(path,headers={},params={}){return call('GET',path+((params.length>0)?'?'+buildQuery(params):''),headers,{});},'post':function(path,headers={},params={},progress=null){return call('POST',path,headers,params,progress);},'put':function(path,headers={},params={},progress=null){return call('PUT',headers,params,progress);},'patch':function(path,headers={},params={},progress=null){return call('PATCH',path,headers,params,progress);},'delete':function(path,headers={},params={},progress=null){return call('DELETE',path,headers,params,progress);},'addGlobalParam':addGlobalParam,'addGlobalHeader':addGlobalHeader}}(window.document);let analytics={create:function(id,source,activity,url){return http.post('/analytics',{'content-type':'application/json'},{id:id,source:source,activity:activity,url:url,version:env.VERSION,setup:env.SETUP});},};return{analytics:analytics,};},true);})(window);(function(window){"use strict";window.ls.container.set('console',function(window){var client=new Appwrite.Client();var endpoint=window.location.origin+'/v1';client.setEndpoint(endpoint).setProject('console').setLocale(APP_ENV.LOCALE);return{client:client,account:new Appwrite.Account(client),avatars:new Appwrite.Avatars(client),databases:new Appwrite.Databases(client),functions:new Appwrite.Functions(client),health:new Appwrite.Health(client),locale:new Appwrite.Locale(client),projects:new Appwrite.Projects(client),storage:new Appwrite.Storage(client),teams:new Appwrite.Teams(client),users:new Appwrite.Users(client)}},true);})(window);(function(window){"use strict";window.ls.container.set('date',function(){function format(format,datetime){if(!datetime){return null;}
|
||||||
return new Intl.DateTimeFormat('en-US',{timeZone:'UTC',hourCycle:'h24',...format}).format(new Date(datetime));}
|
return new Intl.DateTimeFormat(navigator.languages,{hourCycle:'h24',...format}).format(new Date(datetime));}
|
||||||
return{format:format,}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,from,to,){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,from,to));return value;}
|
return{format:format,}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,from,to,){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,from,to));return value;}
|
||||||
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'float':value=parseFloat(value);break;case'string':value=value.toString();if(value.length===0){value=null;}
|
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'float':value=parseFloat(value);break;case'string':value=value.toString();if(value.length===0){value=null;}
|
||||||
break;case'json':value=(value)?JSON.parse(value):[];break;case'array':if(value&&value.constructor&&value.constructor===Array){break;}
|
break;case'json':value=(value)?JSON.parse(value):[];break;case'array':if(value&&value.constructor&&value.constructor===Array){break;}
|
||||||
|
|
|
@ -93,7 +93,10 @@
|
||||||
mode: '',
|
mode: '',
|
||||||
};
|
};
|
||||||
this.headers = {
|
this.headers = {
|
||||||
'x-sdk-version': 'appwrite:web:6.0.0',
|
'x-sdk-name': 'Console',
|
||||||
|
'x-sdk-platform': 'console',
|
||||||
|
'x-sdk-language': 'web',
|
||||||
|
'x-sdk-version': '6.0.0',
|
||||||
'X-Appwrite-Response-Format': '0.15.0',
|
'X-Appwrite-Response-Format': '0.15.0',
|
||||||
};
|
};
|
||||||
this.realtime = {
|
this.realtime = {
|
||||||
|
@ -5125,12 +5128,13 @@
|
||||||
* @param {boolean} enabled
|
* @param {boolean} enabled
|
||||||
* @param {number} maximumFileSize
|
* @param {number} maximumFileSize
|
||||||
* @param {string[]} allowedFileExtensions
|
* @param {string[]} allowedFileExtensions
|
||||||
|
* @param {string} compression
|
||||||
* @param {boolean} encryption
|
* @param {boolean} encryption
|
||||||
* @param {boolean} antivirus
|
* @param {boolean} antivirus
|
||||||
* @throws {AppwriteException}
|
* @throws {AppwriteException}
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
createBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, encryption, antivirus) {
|
createBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, compression, encryption, antivirus) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (typeof bucketId === 'undefined') {
|
if (typeof bucketId === 'undefined') {
|
||||||
throw new AppwriteException('Missing required parameter: "bucketId"');
|
throw new AppwriteException('Missing required parameter: "bucketId"');
|
||||||
|
@ -5164,6 +5168,9 @@
|
||||||
if (typeof allowedFileExtensions !== 'undefined') {
|
if (typeof allowedFileExtensions !== 'undefined') {
|
||||||
payload['allowedFileExtensions'] = allowedFileExtensions;
|
payload['allowedFileExtensions'] = allowedFileExtensions;
|
||||||
}
|
}
|
||||||
|
if (typeof compression !== 'undefined') {
|
||||||
|
payload['compression'] = compression;
|
||||||
|
}
|
||||||
if (typeof encryption !== 'undefined') {
|
if (typeof encryption !== 'undefined') {
|
||||||
payload['encryption'] = encryption;
|
payload['encryption'] = encryption;
|
||||||
}
|
}
|
||||||
|
@ -5211,12 +5218,13 @@
|
||||||
* @param {boolean} enabled
|
* @param {boolean} enabled
|
||||||
* @param {number} maximumFileSize
|
* @param {number} maximumFileSize
|
||||||
* @param {string[]} allowedFileExtensions
|
* @param {string[]} allowedFileExtensions
|
||||||
|
* @param {string} compression
|
||||||
* @param {boolean} encryption
|
* @param {boolean} encryption
|
||||||
* @param {boolean} antivirus
|
* @param {boolean} antivirus
|
||||||
* @throws {AppwriteException}
|
* @throws {AppwriteException}
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
updateBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, encryption, antivirus) {
|
updateBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, compression, encryption, antivirus) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (typeof bucketId === 'undefined') {
|
if (typeof bucketId === 'undefined') {
|
||||||
throw new AppwriteException('Missing required parameter: "bucketId"');
|
throw new AppwriteException('Missing required parameter: "bucketId"');
|
||||||
|
@ -5247,6 +5255,9 @@
|
||||||
if (typeof allowedFileExtensions !== 'undefined') {
|
if (typeof allowedFileExtensions !== 'undefined') {
|
||||||
payload['allowedFileExtensions'] = allowedFileExtensions;
|
payload['allowedFileExtensions'] = allowedFileExtensions;
|
||||||
}
|
}
|
||||||
|
if (typeof compression !== 'undefined') {
|
||||||
|
payload['compression'] = compression;
|
||||||
|
}
|
||||||
if (typeof encryption !== 'undefined') {
|
if (typeof encryption !== 'undefined') {
|
||||||
payload['encryption'] = encryption;
|
payload['encryption'] = encryption;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,13 @@ class Bucket extends Model
|
||||||
'example' => ['jpg', 'png'],
|
'example' => ['jpg', 'png'],
|
||||||
'array' => true
|
'array' => true
|
||||||
])
|
])
|
||||||
|
->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).',
|
||||||
|
'default' => [],
|
||||||
|
'example' => 'gzip',
|
||||||
|
'array' => false
|
||||||
|
])
|
||||||
->addRule('encryption', [
|
->addRule('encryption', [
|
||||||
'type' => self::TYPE_BOOLEAN,
|
'type' => self::TYPE_BOOLEAN,
|
||||||
'description' => 'Bucket is encrypted.',
|
'description' => 'Bucket is encrypted.',
|
||||||
|
|
|
@ -243,6 +243,55 @@ trait StorageBase
|
||||||
return ['bucketId' => $bucketId, 'fileId' => $file['body']['$id'], 'largeFileId' => $largeFile['body']['$id'], 'largeBucketId' => $bucket2['body']['$id']];
|
return ['bucketId' => $bucketId, 'fileId' => $file['body']['$id'], 'largeFileId' => $largeFile['body']['$id'], 'largeBucketId' => $bucket2['body']['$id']];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCreateBucketFileZstdCompression(): array
|
||||||
|
{
|
||||||
|
$bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
|
], [
|
||||||
|
'bucketId' => ID::unique(),
|
||||||
|
'name' => 'Test Bucket',
|
||||||
|
'fileSecurity' => true,
|
||||||
|
'maximumFileSize' => 2000000, //2MB
|
||||||
|
'allowedFileExtensions' => ["jpg", "png"],
|
||||||
|
'compression' => 'zstd',
|
||||||
|
'permissions' => [
|
||||||
|
Permission::read(Role::any()),
|
||||||
|
Permission::create(Role::any()),
|
||||||
|
Permission::update(Role::any()),
|
||||||
|
Permission::delete(Role::any()),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertEquals(201, $bucket['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($bucket['body']['$id']);
|
||||||
|
$this->assertEquals('zstd', $bucket['body']['compression']);
|
||||||
|
|
||||||
|
$bucketId = $bucket['body']['$id'];
|
||||||
|
|
||||||
|
$file = $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/logo.png'), 'image/png', 'logo.png'),
|
||||||
|
'permissions' => [
|
||||||
|
Permission::read(Role::any()),
|
||||||
|
Permission::update(Role::any()),
|
||||||
|
Permission::delete(Role::any()),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertEquals(201, $file['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($file['body']['$id']);
|
||||||
|
$this->assertEquals(true, DateTime::isValid($file['body']['$createdAt']));
|
||||||
|
$this->assertEquals('logo.png', $file['body']['name']);
|
||||||
|
$this->assertEquals('image/png', $file['body']['mimeType']);
|
||||||
|
$this->assertEquals(47218, $file['body']['sizeOriginal']);
|
||||||
|
$this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) != $file['body']['signature']); // should validate that the file is encrypted
|
||||||
|
|
||||||
|
return ['bucketId' => $bucketId];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testCreateBucketFile
|
* @depends testCreateBucketFile
|
||||||
*/
|
*/
|
||||||
|
@ -598,6 +647,50 @@ trait StorageBase
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCreateBucketFileZstdCompression
|
||||||
|
*/
|
||||||
|
public function testFilePreviewZstdCompression(array $data): array
|
||||||
|
{
|
||||||
|
$bucketId = $data['bucketId'];
|
||||||
|
|
||||||
|
$file = $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/logo.png'), 'image/png', 'logo.png'),
|
||||||
|
'permissions' => [
|
||||||
|
Permission::read(Role::any()),
|
||||||
|
Permission::update(Role::any()),
|
||||||
|
Permission::delete(Role::any()),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertEquals(201, $file['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($file['body']['$id']);
|
||||||
|
|
||||||
|
$fileId = $file['body']['$id'];
|
||||||
|
|
||||||
|
//get image preview
|
||||||
|
$file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'width' => 300,
|
||||||
|
'height' => 100,
|
||||||
|
'borderRadius' => '50',
|
||||||
|
'opacity' => '0.5',
|
||||||
|
'output' => 'png',
|
||||||
|
'rotation' => '45',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $file3['headers']['status-code']);
|
||||||
|
$this->assertEquals('image/png', $file3['headers']['content-type']);
|
||||||
|
$this->assertNotEmpty($file3['body']);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testCreateBucketFile
|
* @depends testCreateBucketFile
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue