From 1edf1a7ba150ffc7d20358346233308531add9dc Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 2 Sep 2021 14:15:10 +0545 Subject: [PATCH] custom ID and after pagination --- app/config/collections2.php | 2 +- app/controllers/api/storage.php | 17 ++++++++++++++--- tests/e2e/Services/Storage/StorageBase.php | 6 ++++++ .../Storage/StorageCustomServerTest.php | 9 ++++++--- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index 9da106e025..b23777d5a6 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -1729,7 +1729,7 @@ $collections = [ ], ], 'buckets' => [ - '$collection' => Database::COLLECTIONS, + '$collection' => Database::METADATA, '$id' => 'buckets', '$permissions' => ['read' => ['*']], 'name' => 'Buckets', diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 147ab60f70..2e953d31e0 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -39,6 +39,7 @@ App::post('/v1/storage/buckets') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) + ->param('bucketId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Bucket name', false) ->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) @@ -51,12 +52,13 @@ App::post('/v1/storage/buckets') ->inject('response') ->inject('dbForInternal') ->inject('audits') - ->action(function ($name, $read, $write, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $response, $dbForInternal, $audits) { + ->action(function ($bucketId, $name, $read, $write, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $response, $dbForInternal, $audits) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ /** @var Appwrite\Event\Event $audits */ $data = $dbForInternal->createDocument('buckets', new Document([ + '$id' => $bucketId == 'unique()' ? $dbForInternal->getId() : $bucketId, '$collection' => 'buckets', 'dateCreated' => \time(), 'dateUpdated' => \time(), @@ -95,17 +97,26 @@ App::get('/v1/storage/buckets') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the bucket used as the starting point for the query, excluding the bucket itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : []; + + if (!empty($after)) { + $afterBucket = $dbForInternal->getDocument('buckets', $after); + + if ($afterBucket->isEmpty()) { + throw new Exception("Bucket '{$after}' for the 'after' value not found.", 400); + } + } $response->dynamic(new Document([ - 'buckets' => $dbForInternal->find('buckets', $queries, $limit, $offset, ['_id'], [$orderType]), + 'buckets' => $dbForInternal->find('buckets', $queries, $limit, $offset, ['_id'], [$orderType], $afterBucket ?? null), 'sum' => $dbForInternal->count('buckets', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_BUCKET_LIST); }); diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 764de2e791..b1c136cd8c 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -17,6 +17,7 @@ trait StorageBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders()), [ + 'bucketId' => 'unique()', 'name' => 'Test Bucket', 'maximumFileSize' => 2000000, //2MB 'allowedFileExtensions' => ["jpg", "png"], @@ -55,6 +56,7 @@ trait StorageBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders()), [ + 'bucketId' => 'unique()', 'name' => 'Test Bucket 2', 'read' => ['role:all'], 'write' => ['role:all'], @@ -66,6 +68,7 @@ trait StorageBase 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'fileId' => 'unique()', 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-a/large-file.mp4'), 'video/mp4', 'large-file.mp4'), 'read' => ['role:all'], 'write' => ['role:all'], @@ -87,6 +90,7 @@ trait StorageBase 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'fileId' => 'unique()', 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), 'read' => ['role:all'], 'write' => ['role:all'], @@ -101,6 +105,7 @@ trait StorageBase 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'fileId' => 'unique()', 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-b/kitten-1.png'), 'image/png', 'kitten-1.png'), 'read' => ['role:all'], 'write' => ['role:all'], @@ -117,6 +122,7 @@ trait StorageBase 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'fileId' => 'unique()', 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/disk-a/kitten-3.gif'), 'image/gif', 'kitten-3.gif'), 'read' => ['role:all'], 'write' => ['role:all'], diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 8915bf5526..3cebd434eb 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -22,6 +22,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'bucketId' => 'unique()', 'name' => 'Test Bucket', ]); $this->assertEquals(201, $bucket['headers']['status-code']); @@ -43,6 +44,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'bucketId' => 'unique()', 'name' => '', ]); $this->assertEquals(400, $bucket['headers']['status-code']); @@ -121,14 +123,15 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ + 'bucketId' => 'unique()', 'name' => 'Test Bucket Updated', 'enabled' => false, ]); - $this->assertEquals(201, $bucket['headers']['status-code']); + $this->assertEquals(200, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); $this->assertIsInt($bucket['body']['dateCreated']); $this->assertIsArray($bucket['body']['$read']); @@ -143,7 +146,7 @@ class StorageCustomServerTest extends Scope /** * Test for FAILURE */ - $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $id, array_merge([ + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [