diff --git a/.gitpod.yml b/.gitpod.yml index 811ee54ec8..32ccdb693f 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -5,14 +5,20 @@ tasks: - init: docker-compose pull && docker-compose build && docker run --rm --interactive --tty --volume $PWD:/app composer update --ignore-platform-reqs --optimize-autoloader --no-plugins --no-scripts --prefer-dist - command: | - docker-compose up -d ports: - port: 8080 - onOpen: ignore + onOpen: open-preview visibility: public vscode: extensions: - ms-azuretools.vscode-docker + +github: + # https://www.gitpod.io/docs/prebuilds#github-specific-configuration + prebuilds: + # enable for pull requests coming from forks (defaults to false) + pullRequestsFromForks: true + # add a check to pull requests (defaults to true) + addCheck: false diff --git a/CHANGES.md b/CHANGES.md index 7a9ccd6275..2ac2f910bc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +# Version 0.13.3 +## Bugs +- Fixed search for terms that inlcude `@` characters +- Fixed Bucket permissions +- Fixed file upload error in UI +- Fixed input field for float attributes in UI +- Fixed `appwrite-executor` restart behavior in docker-compose.yml + # Version 0.13.2 ## Bugs - Fixed global issue with write permissions diff --git a/README-CN.md b/README-CN.md index eefa1530ee..7c11852d37 100644 --- a/README-CN.md +++ b/README-CN.md @@ -59,7 +59,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` ### Windows @@ -71,7 +71,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` #### PowerShell @@ -81,7 +81,7 @@ docker run -it --rm , --volume /var/run/docker.sock:/var/run/docker.sock , --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw , --entrypoint="install" , - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index 326a2cda2c..b3fd3d83cd 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Table of Contents: Appwrite backend server is designed to run in a container environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool like Kubernetes, Docker Swarm, or Rancher. -The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine: +The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine: ### Unix @@ -62,7 +62,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` ### Windows @@ -74,7 +74,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` #### PowerShell @@ -84,7 +84,7 @@ docker run -it --rm , --volume /var/run/docker.sock:/var/run/docker.sock , --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw , --entrypoint="install" , - appwrite/appwrite:0.13.2 + appwrite/appwrite:0.13.3 ``` Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after installation completes. diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index a4c705596c..1cf78b07e3 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1687,7 +1687,7 @@ App::get('/v1/database/collections/:collectionId/documents') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).') - ->param('queries', [], new ArrayList(new Text(0), 100), 'Array of query strings.', true) + ->param('queries', [], new ArrayList(new Text(0), 100), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/database#querying-documents).', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) ->param('cursor', '', new UID(), 'ID of the document used as the starting point for the query, excluding the document itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) @@ -1949,7 +1949,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') ->label('sdk.response.model', Response::MODEL_DOCUMENT) ->param('collectionId', null, new UID(), 'Collection ID.') ->param('documentId', null, new UID(), 'Document ID.') - ->param('data', [], new JSON(), 'Document data as JSON object.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.') ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('response') diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 80d3fb1efc..4b6b0c94e8 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -715,7 +715,7 @@ App::get('/v1/storage/buckets/:bucketId/files') /** @var Appwrite\Stats\Stats $usage */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -738,9 +738,7 @@ App::get('/v1/storage/buckets/:bucketId/files') if (!empty($cursor)) { if ($bucket->getAttribute('permission') === 'bucket') { - $cursorFile = Authorization::skip(function () use ($dbForProject, $bucket, $cursor) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor); - }); + $cursorFile = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor)); } else { $cursorFile = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor); } @@ -757,9 +755,7 @@ App::get('/v1/storage/buckets/:bucketId/files') } if ($bucket->getAttribute('permission') === 'bucket') { - $files = Authorization::skip(function () use ($dbForProject, $bucket, $queries, $limit, $offset, $cursor, $cursorDirection, $orderType) { - return $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection); - }); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection)); } else { $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection); } @@ -799,7 +795,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') /** @var Appwrite\Stats\Stats $usage */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -815,9 +811,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') } if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $bucket, $fileId) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -825,10 +819,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) { throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND); } + $usage ->setParam('storage.files.read', 1) ->setParam('bucketId', $bucketId) ; + $response->dynamic($file, Response::MODEL_FILE); }); @@ -879,7 +875,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception('Imagick extension is missing', 500, Exception::GENERAL_SERVER_ERROR); } - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -907,9 +903,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') if ($bucket->getAttribute('permission') === 'bucket') { // skip authorization - $file = Authorization::skip(function () use ($dbForProject, $bucket, $fileId) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -1048,7 +1042,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') /** @var Utopia\Storage\Device $deviceFiles */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -1064,9 +1058,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $fileId, $bucket) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -1193,7 +1185,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') /** @var Utopia\Storage\Device $deviceFiles */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -1209,9 +1201,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $fileId, $bucket) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -1356,7 +1346,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') /** @var Appwrite\Event\Event $events */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $read = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user $write = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; @@ -1390,9 +1380,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $fileId, $bucket) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -1401,18 +1389,15 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND); } + $file + ->setAttribute('$read', $read) + ->setAttribute('$write', $write) + ; + if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $fileId, $bucket, $file, $read, $write) { - return $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file - ->setAttribute('$read', $read) - ->setAttribute('$write', $write) - ); - }); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } else { - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file - ->setAttribute('$read', $read) - ->setAttribute('$write', $write) - ); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } $events->setParam('bucket', $bucket->getArrayCopy()); @@ -1462,7 +1447,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') /** @var Utopia\Storage\Device $deviceFiles */ /** @var string $mode */ - $bucket = $dbForProject->getDocument('buckets', $bucketId); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { @@ -1478,9 +1463,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') } if ($bucket->getAttribute('permission') === 'bucket') { - $file = Authorization::skip(function () use ($dbForProject, $fileId, $bucket) { - return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } @@ -1506,9 +1489,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') $deviceLocal->delete($cacheDir, true); if ($bucket->getAttribute('permission') === 'bucket') { - $deleted = Authorization::skip(function () use ($dbForProject, $fileId, $bucket) { - return $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); - }); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); } else { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); } diff --git a/app/init.php b/app/init.php index ab18896bcb..7ed0152b24 100644 --- a/app/init.php +++ b/app/init.php @@ -69,8 +69,8 @@ const APP_LIMIT_USERS = 10000; const APP_LIMIT_ANTIVIRUS = 20000000; //20MB const APP_LIMIT_ENCRYPTION = 20000000; //20MB const APP_LIMIT_COMPRESSION = 20000000; //20MB -const APP_CACHE_BUSTER = 302; -const APP_VERSION_STABLE = '0.13.2'; +const APP_CACHE_BUSTER = 303; +const APP_VERSION_STABLE = '0.13.3'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/app/views/console/database/collection.phtml b/app/views/console/database/collection.phtml index af53507797..53921ac571 100644 --- a/app/views/console/database/collection.phtml +++ b/app/views/console/database/collection.phtml @@ -762,21 +762,21 @@ $logs = $this->getParam('logs', null);
- +
- +