From a5eb89fc1b2ce44fc0277c5eea4a0085faff899e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 14 Jun 2021 17:17:09 +0545 Subject: [PATCH 01/31] wip --- app/controllers/api/storage.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index c4fe8c8494..f05457d59d 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -24,6 +24,31 @@ use Appwrite\Utopia\Response; use Utopia\Config\Config; use Utopia\Validator\Numeric; +App::post('/v1/storage/buckets') + ->desc('Create storage bucket') + ->groups(['api', 'storage']) + ->label('scope', 'buckets.write') + ->label('event', 'storage.buckets.create') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'storage') + ->label('sdk.method', 'createBucket') + ->label('sdk.description', '/docs/references/storage/create-bucket.md') + ->label('sdk.response.code', Response::STATUS_CODE_CREATED) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_BUCKET) + ->param('file', [], new File(), 'Binary file.', false) + ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->inject('request') + ->inject('response') + ->inject('projectDB') + ->inject('user') + ->inject('audits') + ->inject('usage') + ->action(function ($file, $read, $write, $request, $response, $projectDB, $user, $audits, $usage) { + + }); + App::post('/v1/storage/files') ->desc('Create File') ->groups(['api', 'storage']) From be512471f88b1d2bdc10a8482e9a5b408bfc80cb Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 14 Jun 2021 17:30:26 +0545 Subject: [PATCH 02/31] fix description typo --- src/Appwrite/Utopia/Response/Model/Bucket.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index e64d4d3b9a..4f657f009b 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -19,14 +19,14 @@ class Bucket extends Model ]) ->addRule('$permissions', [ 'type' => Response::MODEL_PERMISSIONS, - 'description' => 'File permissions.', + 'description' => 'Bucket permissions.', 'default' => new \stdClass, 'example' => new \stdClass, 'array' => false, ]) ->addRule('dateCreated', [ 'type' => self::TYPE_INTEGER, - 'description' => 'File creation date in Unix timestamp.', + 'description' => 'Bucket creation date in Unix timestamp.', 'default' => 0, 'example' => 1592981250, ]) From d0f7ab7a1986343e4c160213e32bc55dbab2f59f Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 14 Jun 2021 17:44:47 +0545 Subject: [PATCH 03/31] create bucket endpoint --- app/controllers/api/storage.php | 57 ++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index f05457d59d..653acec66c 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -6,6 +6,7 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\WhiteList; use Utopia\Validator\Range; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; use Utopia\Validator\HexColor; use Utopia\Cache\Cache; use Utopia\Cache\Adapter\Filesystem; @@ -22,7 +23,9 @@ use Utopia\Image\Image; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Response; use Utopia\Config\Config; -use Utopia\Validator\Numeric; +use Utopia\Validator\Integer; +use Appwrite\Database\Exception\Authorization as AuthorizationException; +use Appwrite\Database\Exception\Structure as StructureException; App::post('/v1/storage/buckets') ->desc('Create storage bucket') @@ -36,16 +39,60 @@ 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('file', [], new File(), 'Binary file.', false) + ->param('name', '', new Text(128), 'Bucket name', false) + ->param('maximumFileSize', 0, new Integer(), 'Maximum file size supported', false) + ->param('allowedFileExtensions', '*', new Text(128), 'Allowed file extensions', false) + ->param('enabled', true, new Boolean(), 'Bucket enabled', true) + ->param('adapter', 'local', new WhiteList(['local']), 'Storage adapter', true) + ->param('encryption', true, new Boolean(), 'encryption is enabled', true) + ->param('antiVirus', true, new Boolean(), 'Virus scanning is enabled', true) ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) - ->inject('request') ->inject('response') ->inject('projectDB') ->inject('user') ->inject('audits') - ->inject('usage') - ->action(function ($file, $read, $write, $request, $response, $projectDB, $user, $audits, $usage) { + ->action(function ($name, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $read, $write, $response, $projectDB, $user, $audits) { + /** @var Utopia\Swoole\Request $request */ + /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $projectDB */ + /** @var Appwrite\Database\Document $user */ + /** @var Appwrite\Event\Event $audits */ + + try { + $data = $projectDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_BUCKETS, + 'dateCreated' => \time(), + 'name' => $name, + 'maximumFileSize' => $maximumFileSize, + 'allowedFileExtensions' => $allowedFileExtensions, + 'enabled' => $enabled, + 'adapter' => $adapter, + 'encryption' => $encryption, + 'antiVirus' => $antiVirus, + ]); + $data['$permissions'] = [ + '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 ?? [], // By default set write permissions for user + ]; + } catch (AuthorizationException $exception) { + throw new Exception('Unauthorized permissions', 401); + } catch (StructureException $exception) { + throw new Exception('Bad structure. '.$exception->getMessage(), 400); + } catch (\Exception $exception) { + throw new Exception('Failed saving document to DB', 500); + } + + $audits + ->setParam('event', 'database.collections.create') + ->setParam('resource', 'database/collection/'.$data->getId()) + ->setParam('data', $data->getArrayCopy()) + ; + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($data, Response::MODEL_BUCKET) + ; }); From 22da32a53f1a19e4542ffff1903458447c78f7e7 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 11:09:39 +0545 Subject: [PATCH 04/31] fix response model def for bucket --- src/Appwrite/Utopia/Response.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index e0b96834e3..5530758e64 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -21,6 +21,7 @@ use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; use Appwrite\Utopia\Response\Model\File; +use Appwrite\Utopia\Response\Model\Bucket; use Appwrite\Utopia\Response\Model\Func; use Appwrite\Utopia\Response\Model\JWT; use Appwrite\Utopia\Response\Model\Key; @@ -185,6 +186,7 @@ class Response extends SwooleResponse ->setModel(new JWT()) ->setModel(new Locale()) ->setModel(new File()) + ->setModel(new Bucket()) ->setModel(new Team()) ->setModel(new Membership()) ->setModel(new Func()) From f7c27e17276c50ba714229fa8b3d6b5ad5172c4b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 11:42:38 +0545 Subject: [PATCH 05/31] fix name for buckets collection --- app/config/collections.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index 3b28dd368d..a6a11f9ae3 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1440,7 +1440,7 @@ $collections = [ '$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS, '$id' => Database::SYSTEM_COLLECTION_BUCKETS, '$permissions' => ['read' => ['*']], - 'name' => 'File', + 'name' => 'Bucket', 'structure' => true, 'rules' => [ [ From aabcc8eb09982e8a85996734283b7b1f70a1f04a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 12:22:51 +0545 Subject: [PATCH 06/31] fixing structure --- app/config/collections.php | 13 +++++++++++-- src/Appwrite/Utopia/Response/Model/Bucket.php | 6 ++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index a6a11f9ae3..d21010c54c 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1452,13 +1452,22 @@ $collections = [ 'required' => false, 'array' => false, ], + [ + '$collection' => Database::SYSTEM_COLLECTION_RULES, + 'label' => 'Date Updated', + 'key' => 'dateUpdated', + 'type' => Database::SYSTEM_VAR_TYPE_NUMERIC, + 'default' => 0, + 'required' => false, + 'array' => false, + ], [ '$collection' => Database::SYSTEM_COLLECTION_RULES, 'label' => 'Enabled', 'key' => 'enabled', 'type' => Database::SYSTEM_VAR_TYPE_BOOLEAN, 'default' => true, - 'required' => false, + 'required' => true, 'array' => false, ], [ @@ -1505,7 +1514,7 @@ $collections = [ 'type' => Database::SYSTEM_VAR_TYPE_TEXT, 'default' => '', 'required' => true, - 'array' => false, + 'array' => true, ], [ '$collection' => Database::SYSTEM_COLLECTION_RULES, diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index 4f657f009b..7fdadacd9c 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -30,6 +30,12 @@ class Bucket extends Model 'default' => 0, 'example' => 1592981250, ]) + ->addRule('dateUpdated', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Bucket updated date in Unix timestamp.', + 'default' => 0, + 'example' => 1592981250, + ]) ->addRule('name', [ 'type' => self::TYPE_STRING, 'description' => 'Bucket name.', From fe34b6685ed039dee41a074b3d3192205b63acce Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 12:23:05 +0545 Subject: [PATCH 07/31] buckets.write scope --- app/config/roles.php | 2 ++ app/config/scopes.php | 3 +++ tests/e2e/Scopes/ProjectCustom.php | 1 + 3 files changed, 6 insertions(+) diff --git a/app/config/roles.php b/app/config/roles.php index 3e06ddbfde..3aabc0b931 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -13,6 +13,7 @@ $member = [ 'documents.write', 'files.read', 'files.write', + 'buckets.write', 'projects.read', 'projects.write', 'locale.read', @@ -28,6 +29,7 @@ $admins = [ 'documents.write', 'files.read', 'files.write', + 'buckets.write', 'users.read', 'users.write', 'collections.read', diff --git a/app/config/scopes.php b/app/config/scopes.php index 088502c5d8..47d93458bf 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -31,6 +31,9 @@ return [ // List of publicly visible scopes 'files.write' => [ 'description' => 'Access to create, update, and delete your project\'s storage files', ], + 'buckets.write' => [ + 'description' => 'Access to create, update, and delete your project\'s storage buckets', + ], 'functions.read' => [ 'description' => 'Access to read your project\'s functions and code tags', ], diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 3f80285282..dc5673ce83 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -73,6 +73,7 @@ trait ProjectCustom 'documents.write', 'files.read', 'files.write', + 'buckets.write', 'functions.read', 'functions.write', 'execution.read', From 19173813798dfc428f1dd08dbfaf93d3dbec5b8d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 12:28:10 +0545 Subject: [PATCH 08/31] fix create bucket issue --- app/controllers/api/storage.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 653acec66c..9f4e3d6e54 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -40,8 +40,8 @@ App::post('/v1/storage/buckets') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('name', '', new Text(128), 'Bucket name', false) - ->param('maximumFileSize', 0, new Integer(), 'Maximum file size supported', false) - ->param('allowedFileExtensions', '*', new Text(128), 'Allowed file extensions', false) + ->param('maximumFileSize', 0, new Integer(), 'Maximum file size supported', true) + ->param('allowedFileExtensions', ['*'], new ArrayList(new Text(64)), 'Allowed file extensions', true) ->param('enabled', true, new Boolean(), 'Bucket enabled', true) ->param('adapter', 'local', new WhiteList(['local']), 'Storage adapter', true) ->param('encryption', true, new Boolean(), 'encryption is enabled', true) @@ -60,7 +60,7 @@ App::post('/v1/storage/buckets') /** @var Appwrite\Event\Event $audits */ try { - $data = $projectDB->createDocument([ + $data = [ '$collection' => Database::SYSTEM_COLLECTION_BUCKETS, 'dateCreated' => \time(), 'name' => $name, @@ -70,11 +70,12 @@ App::post('/v1/storage/buckets') 'adapter' => $adapter, 'encryption' => $encryption, 'antiVirus' => $antiVirus, - ]); + ]; $data['$permissions'] = [ '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 ?? [], // By default set write permissions for user ]; + $data = $projectDB->createDocument($data); } catch (AuthorizationException $exception) { throw new Exception('Unauthorized permissions', 401); } catch (StructureException $exception) { From 3a9e6f829509292087f62424ff5897c1943e0bf7 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 12:28:15 +0545 Subject: [PATCH 09/31] create bucket test --- tests/e2e/Services/Storage/StorageBase.php | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 395eb8ce4f..a60cb795ae 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -244,4 +244,35 @@ trait StorageBase return $data; } + + public function testCreateBucket():array + { + /** + * Test for SUCCESS + */ + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Test Bucket', + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + $this->assertNotEmpty($bucket['body']['$id']); + $this->assertIsInt($bucket['body']['dateCreated']); + $this->assertEquals('Test Bucket', $bucket['body']['name']); + $this->assertEquals(true, $bucket['body']['enabled']); + $bucketId = $bucket['body']['$id']; + /** + * Test for FAILURE + */ + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => '', + ]); + $this->assertEquals(400, $bucket['headers']['status-code']); + + return ['bucketId' => $bucketId]; + } } \ No newline at end of file From 382aab0deeded7f547599b237f4ce20a66ea95f6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 13:08:06 +0545 Subject: [PATCH 10/31] buckets.read scope --- app/config/roles.php | 2 ++ app/config/scopes.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/app/config/roles.php b/app/config/roles.php index 3aabc0b931..ae9157eaa7 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -13,6 +13,7 @@ $member = [ 'documents.write', 'files.read', 'files.write', + 'buckets.read', 'buckets.write', 'projects.read', 'projects.write', @@ -29,6 +30,7 @@ $admins = [ 'documents.write', 'files.read', 'files.write', + 'buckets.read', 'buckets.write', 'users.read', 'users.write', diff --git a/app/config/scopes.php b/app/config/scopes.php index 47d93458bf..303c834759 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -31,6 +31,9 @@ return [ // List of publicly visible scopes 'files.write' => [ 'description' => 'Access to create, update, and delete your project\'s storage files', ], + 'buckets.read' => [ + 'description' => 'Access to read your project\'s storage buckets', + ], 'buckets.write' => [ 'description' => 'Access to create, update, and delete your project\'s storage buckets', ], From 081d3ecbdec9127de162ed7a52600d0237e24062 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 13:08:22 +0545 Subject: [PATCH 11/31] list buckets endpoint --- app/controllers/api/storage.php | 37 ++++++++++++++++++++++ tests/e2e/Services/Storage/StorageBase.php | 22 +++++++++++++ 2 files changed, 59 insertions(+) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 9f4e3d6e54..a646f000fe 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -97,6 +97,43 @@ App::post('/v1/storage/buckets') }); +App::get('/v1/storage/buckets') + ->desc('List buckets') + ->groups(['api', 'storage']) + ->label('scope', 'buckets.read') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'storage') + ->label('sdk.method', 'listBuckets') + ->label('sdk.description', '/docs/references/storage/list-buckets.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) + ->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('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) + ->inject('response') + ->inject('projectDB') + ->action(function ($search, $limit, $offset, $orderType, $response, $projectDB) { + /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $projectDB */ + + $results = $projectDB->getCollection([ + 'limit' => $limit, + 'offset' => $offset, + 'orderType' => $orderType, + 'search' => $search, + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_BUCKETS, + ], + ]); + + $response->dynamic(new Document([ + 'sum' => $projectDB->getSum(), + 'buckets' => $results + ]), Response::MODEL_BUCKET_LIST); + }); + App::post('/v1/storage/files') ->desc('Create File') ->groups(['api', 'storage']) diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index a60cb795ae..a20721e22d 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -275,4 +275,26 @@ trait StorageBase return ['bucketId' => $bucketId]; } + + /** + * @depends testCreateBucket + */ + public function testListBucket($data): array + { + $id = $data['bucketId'] ?? ''; + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertEquals($id, $response['body']['buckets'][0]['$id']); + $this->assertEquals('Test Bucket', $response['body']['buckets'][0]['name']); + + return $data; + } } \ No newline at end of file From 0bb5718b2f037c4fa09a71b2a13a951b1472bcb2 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 13:33:59 +0545 Subject: [PATCH 12/31] get bucket endpoint and test --- app/controllers/api/storage.php | 28 +++++++++++++++ tests/e2e/Services/Storage/StorageBase.php | 40 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index a646f000fe..9e1cd6c558 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -134,6 +134,34 @@ App::get('/v1/storage/buckets') ]), Response::MODEL_BUCKET_LIST); }); +App::get('/v1/storage/buckets/:bucketId') + ->desc('Get Bucket') + ->groups(['api', 'storage']) + ->label('scope', 'buckets.read') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'storage') + ->label('sdk.method', 'getBucket') + ->label('sdk.description', '/docs/references/storage/get-bucket.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_BUCKET) + ->param('bucketId', '', new UID(), 'Bucket unique ID.') + ->inject('response') + ->inject('projectDB') + ->action(function ($bucketId, $response, $projectDB) { + /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $projectDB */ + + $bucket = $projectDB->getDocument($bucketId); + + if (empty($bucket->getId()) || Database::SYSTEM_COLLECTION_BUCKETS != $bucket->getCollection()) { + throw new Exception('Bucket not found', 404); + } + + $response->dynamic($bucket, Response::MODEL_BUCKET); + }); + + App::post('/v1/storage/files') ->desc('Create File') ->groups(['api', 'storage']) diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index a20721e22d..bdd277752a 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -297,4 +297,44 @@ trait StorageBase return $data; } + + /** + * @depends testCreateBucket + */ + public function testGetBucket($data): array + { + $id = $data['bucketId'] ?? ''; + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $id, + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertEquals($id, $response['body']['$id']); + $this->assertEquals('Test Bucket', $response['body']['name']); + + /** + * Test for FAILURE + */ + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(400, $response['headers']['status-code']); + + return $data; + } } \ No newline at end of file From 69390029323177dd65c9f7a9c091e4dc9dc1f52a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 14:19:49 +0545 Subject: [PATCH 13/31] create bucket fixing with new db --- app/config/collections2.php | 125 ++++++++++++++++++++++++++++++++ app/controllers/api/storage.php | 32 ++++---- composer.lock | 6 +- 3 files changed, 142 insertions(+), 21 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index b130092886..e485bbd444 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -967,6 +967,131 @@ $collections = [ ] ], ], + 'buckets' => [ + '$collection' => Database::COLLECTIONS, + '$id' => 'buckets', + '$permissions' => ['read' => ['*']], + 'name' => 'Buckets', + 'structure' => true, + 'attributes' => [ + [ + '$id' => 'dateCreated', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'signed' => false, + 'size' => 0, + 'required' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'dateUpdated', + 'type' => Database::VAR_INTEGER, + 'size' => 0, + 'format' => '', + 'signed' => true, + 'required' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'enabled', + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => 'name', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 128, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + + 'label' => 'Adapter', + '$id' => 'adapter', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 64, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + + '$id' => 'adapterCredentials', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 16384, + 'format' => '', + 'required' => false, + 'array' => false, + 'filters' => ['json'] + ], + [ + '$id' => 'maximumFileSize', + 'type' => Database::VAR_INTEGER, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => 'allowedFileExtensions', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 64, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => true, + ], + [ + + 'label' => 'Encryption', + '$id' => 'encryption', + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + + 'label' => 'Virus Scan', + '$id' => 'antiVirus', + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + ], + 'indexes' => [ + [ + '$id' => '_fulltext_name', + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [1024], + 'orders' => [Database::ORDER_ASC], + ] + ] + ] ]; /* diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 7fa14f8d3b..935d76e05d 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -26,7 +26,6 @@ use Utopia\Validator\Integer; use Appwrite\Database\Exception\Authorization as AuthorizationException; use Appwrite\Database\Exception\Structure as StructureException; use Utopia\Database\Query; -use Utopia\Validator\Numeric; App::post('/v1/storage/buckets') ->desc('Create storage bucket') @@ -50,20 +49,21 @@ App::post('/v1/storage/buckets') ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->inject('response') - ->inject('projectDB') + ->inject('dbForInternal') ->inject('user') ->inject('audits') - ->action(function ($name, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $read, $write, $response, $projectDB, $user, $audits) { + ->action(function ($name, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $read, $write, $response, $dbForInternal, $user, $audits) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Database\Database $projectDB */ + /** @var Utopia\Database\Database $dbForInternal */ /** @var Appwrite\Database\Document $user */ /** @var Appwrite\Event\Event $audits */ try { $data = [ - '$collection' => Database::SYSTEM_COLLECTION_BUCKETS, + '$collection' => 'buckets', 'dateCreated' => \time(), + 'dateUpdated' => \time(), 'name' => $name, 'maximumFileSize' => $maximumFileSize, 'allowedFileExtensions' => $allowedFileExtensions, @@ -72,30 +72,26 @@ App::post('/v1/storage/buckets') 'encryption' => $encryption, 'antiVirus' => $antiVirus, ]; - $data['$permissions'] = [ - '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 ?? [], // By default set write permissions for user - ]; - $data = $projectDB->createDocument($data); + + $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user + $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; // By default set write permissions for user + $data = $dbForInternal->createDocument('buckets', new Document($data)); } catch (AuthorizationException $exception) { throw new Exception('Unauthorized permissions', 401); } catch (StructureException $exception) { - throw new Exception('Bad structure. '.$exception->getMessage(), 400); - } catch (\Exception $exception) { + throw new Exception('Bad structure. ' . $exception->getMessage(), 400); + } catch (\Exception$exception) { throw new Exception('Failed saving document to DB', 500); } $audits ->setParam('event', 'database.collections.create') - ->setParam('resource', 'database/collection/'.$data->getId()) + ->setParam('resource', 'database/collection/' . $data->getId()) ->setParam('data', $data->getArrayCopy()) ; - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($data, Response::MODEL_BUCKET) - ; - + $response->setStatusCode(Response::STATUS_CODE_CREATED); + $response->dynamic2($data, Response::MODEL_BUCKET); }); App::post('/v1/storage/files') diff --git a/composer.lock b/composer.lock index 20e5ea98ae..9d12880f2c 100644 --- a/composer.lock +++ b/composer.lock @@ -1704,7 +1704,7 @@ "source": { "type": "git", "url": "https://github.com/lohanidamodar/audit", - "reference": "b3ca9fa928fdec8c966596cbd85ee1141c79b6eb" + "reference": "d5591321161b81043c45be3c53ce9dcfa2d81d72" }, "require": { "ext-pdo": "*", @@ -1738,7 +1738,7 @@ "upf", "utopia" ], - "time": "2021-06-13T07:41:15+00:00" + "time": "2021-06-14T07:38:18+00:00" }, { "name": "utopia-php/cache", @@ -6195,5 +6195,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } From b7eb26bc96189cc672e3a25f69aea1d93d6c99d6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 14:22:23 +0545 Subject: [PATCH 14/31] fix list bucket with new db --- app/controllers/api/storage.php | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 18424ba553..40f6e88bdf 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -110,24 +110,16 @@ App::get('/v1/storage/buckets') ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') - ->inject('projectDB') - ->action(function ($search, $limit, $offset, $orderType, $response, $projectDB) { + ->inject('dbForInternal') + ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Database\Database $projectDB */ + /** @var Utopia\Database\Database $dbForInternal */ - $results = $projectDB->getCollection([ - 'limit' => $limit, - 'offset' => $offset, - 'orderType' => $orderType, - 'search' => $search, - 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_BUCKETS, - ], - ]); + $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : []; - $response->dynamic(new Document([ - 'sum' => $projectDB->getSum(), - 'buckets' => $results + $response->dynamic2(new Document([ + 'buckets' => $dbForInternal->find('buckets', $queries, $limit, $offset, ['_id'], [$orderType]), + 'sum' => $dbForInternal->count('buckets', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_BUCKET_LIST); }); From 62f7373e776adaee7554560fa9444d17b9c81707 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 14:24:36 +0545 Subject: [PATCH 15/31] fix get bucket with new db --- app/controllers/api/storage.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index f425b700f7..a4b483d9b4 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -136,18 +136,18 @@ App::get('/v1/storage/buckets/:bucketId') ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->inject('response') - ->inject('projectDB') - ->action(function ($bucketId, $response, $projectDB) { + ->inject('dbForInternal') + ->action(function ($bucketId, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Database\Database $projectDB */ + /** @var Utopia\Database\Database $dbForInternal */ - $bucket = $projectDB->getDocument($bucketId); + $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if (empty($bucket->getId()) || Database::SYSTEM_COLLECTION_BUCKETS != $bucket->getCollection()) { + if (empty($bucket->getId())) { throw new Exception('Bucket not found', 404); } - $response->dynamic($bucket, Response::MODEL_BUCKET); + $response->dynamic2($bucket, Response::MODEL_BUCKET); }); From b1ebb150cb6e2a5e830a6421363c6b9948d68e42 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 14:29:36 +0545 Subject: [PATCH 16/31] fix response model --- src/Appwrite/Utopia/Response/Model/Bucket.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index 7fdadacd9c..cb1e1a5e16 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -17,12 +17,19 @@ class Bucket extends Model 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('$permissions', [ - 'type' => Response::MODEL_PERMISSIONS, - 'description' => 'Bucket permissions.', - 'default' => new \stdClass, - 'example' => new \stdClass, - 'array' => false, + ->addRule('$read', [ + 'type' => self::TYPE_STRING, + 'description' => 'File read permissions.', + 'default' => [], + 'example' => ['role:all'], + 'array' => true, + ]) + ->addRule('$write', [ + 'type' => self::TYPE_STRING, + 'description' => 'File write permissions.', + 'default' => [], + 'example' => ['user:608f9da25e7e1'], + 'array' => true, ]) ->addRule('dateCreated', [ 'type' => self::TYPE_INTEGER, From 667161d46a2b0c71a3046483f5eaf9428b22406e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 15 Jun 2021 14:44:00 +0545 Subject: [PATCH 17/31] with new db this is not required --- app/config/collections.php | 100 ------------------------------------- 1 file changed, 100 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index f7c8d73fa8..f69651ca33 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1436,106 +1436,6 @@ $collections = [ ], ], ], - Database::SYSTEM_COLLECTION_BUCKETS => [ - '$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS, - '$id' => Database::SYSTEM_COLLECTION_BUCKETS, - '$permissions' => ['read' => ['*']], - 'name' => 'Bucket', - 'structure' => true, - 'rules' => [ - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Date Created', - 'key' => 'dateCreated', - 'type' => Database::SYSTEM_VAR_TYPE_NUMERIC, - 'default' => 0, - 'required' => false, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Date Updated', - 'key' => 'dateUpdated', - 'type' => Database::SYSTEM_VAR_TYPE_NUMERIC, - 'default' => 0, - 'required' => false, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Enabled', - 'key' => 'enabled', - 'type' => Database::SYSTEM_VAR_TYPE_BOOLEAN, - 'default' => true, - 'required' => true, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Name', - 'key' => 'name', - 'type' => Database::SYSTEM_VAR_TYPE_TEXT, - 'default' => '', - 'required' => true, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Adapter', - 'key' => 'adapter', - 'type' => Database::SYSTEM_VAR_TYPE_TEXT, - 'default' => '', - 'required' => true, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Adapter Crednetials', - 'key' => 'adapterCredentials', - 'type' => Database::SYSTEM_VAR_TYPE_TEXT, - 'default' => '', - 'required' => false, - 'array' => false, - 'filter' => ['json'] - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Maximum File Size', - 'key' => 'maximumFileSize', - 'type' => Database::SYSTEM_VAR_TYPE_NUMERIC, - 'default' => 0, - 'required' => true, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Allowed File Extensions', - 'key' => 'allowedFileExtensions', - 'type' => Database::SYSTEM_VAR_TYPE_TEXT, - 'default' => '', - 'required' => true, - 'array' => true, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Encryption', - 'key' => 'encryption', - 'type' => Database::SYSTEM_VAR_TYPE_BOOLEAN, - 'default' => true, - 'required' => true, - 'array' => false, - ], - [ - '$collection' => Database::SYSTEM_COLLECTION_RULES, - 'label' => 'Virus Scan', - 'key' => 'antiVirus', - 'type' => Database::SYSTEM_VAR_TYPE_BOOLEAN, - 'default' => true, - 'required' => true, - 'array' => false, - ], - ], - ], Database::SYSTEM_COLLECTION_FUNCTIONS => [ '$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS, '$id' => Database::SYSTEM_COLLECTION_FUNCTIONS, From 091152ca461472b36a3b15b6fcb1af45ed99f977 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:08:31 +0545 Subject: [PATCH 18/31] update collection structure --- app/config/collections2.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index e485bbd444..de3bcce83e 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -1015,8 +1015,6 @@ $collections = [ 'array' => false, ], [ - - 'label' => 'Adapter', '$id' => 'adapter', 'type' => Database::VAR_STRING, 'signed' => true, @@ -1058,8 +1056,6 @@ $collections = [ 'array' => true, ], [ - - 'label' => 'Encryption', '$id' => 'encryption', 'type' => Database::VAR_BOOLEAN, 'signed' => true, @@ -1070,8 +1066,6 @@ $collections = [ 'array' => false, ], [ - - 'label' => 'Virus Scan', '$id' => 'antiVirus', 'type' => Database::VAR_BOOLEAN, 'signed' => true, From 94c91cc52a39a581e291cf24f4af24b601857cef Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:11:34 +0545 Subject: [PATCH 19/31] Apply suggestions from code review Co-authored-by: Eldad A. Fux --- app/controllers/api/storage.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 40f6e88bdf..638e80c944 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -32,7 +32,7 @@ App::post('/v1/storage/buckets') ->groups(['api', 'storage']) ->label('scope', 'buckets.write') ->label('event', 'storage.buckets.create') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'storage') ->label('sdk.method', 'createBucket') ->label('sdk.description', '/docs/references/storage/create-bucket.md') @@ -40,12 +40,12 @@ App::post('/v1/storage/buckets') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('name', '', new Text(128), 'Bucket name', false) - ->param('maximumFileSize', 0, new Integer(), 'Maximum file size supported', true) + ->param('maximumFileSize', 0, new Integer(), 'Maximum file size allowed.', true) ->param('allowedFileExtensions', ['*'], new ArrayList(new Text(64)), 'Allowed file extensions', true) - ->param('enabled', true, new Boolean(), 'Bucket enabled', true) - ->param('adapter', 'local', new WhiteList(['local']), 'Storage adapter', true) - ->param('encryption', true, new Boolean(), 'encryption is enabled', true) - ->param('antiVirus', true, new Boolean(), 'Virus scanning is enabled', true) + ->param('enabled', true, new Boolean(), 'Is bucket enabled?', true) + ->param('adapter', 'local', new WhiteList(['local']), 'Storage adapter.', true) + ->param('encryption', true, new Boolean(), 'Is encryption enabled?', true) + ->param('antiVirus', true, new Boolean(), 'Is virus scanning enabled?', true) ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->inject('response') @@ -685,4 +685,4 @@ App::delete('/v1/storage/files/:fileId') ; $response->noContent(); - }); \ No newline at end of file + }); From 988004e27f256f4b704572808c9a7e7656638ffc Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:16:07 +0545 Subject: [PATCH 20/31] suggested updates --- app/controllers/api/storage.php | 44 ++++++++++++++------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 638e80c944..f157abd774 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -40,49 +40,41 @@ App::post('/v1/storage/buckets') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('name', '', new Text(128), 'Bucket name', false) + ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('maximumFileSize', 0, new Integer(), 'Maximum file size allowed.', true) ->param('allowedFileExtensions', ['*'], new ArrayList(new Text(64)), 'Allowed file extensions', true) ->param('enabled', true, new Boolean(), 'Is bucket enabled?', true) ->param('adapter', 'local', new WhiteList(['local']), 'Storage adapter.', true) ->param('encryption', true, new Boolean(), 'Is encryption enabled?', true) ->param('antiVirus', true, new Boolean(), 'Is virus scanning enabled?', true) - ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->inject('response') ->inject('dbForInternal') ->inject('user') ->inject('audits') - ->action(function ($name, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $read, $write, $response, $dbForInternal, $user, $audits) { + ->action(function ($name, $read, $write, $maximumFileSize, $allowedFileExtensions, $enabled, $adapter, $encryption, $antiVirus, $response, $dbForInternal, $user, $audits) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ /** @var Appwrite\Database\Document $user */ /** @var Appwrite\Event\Event $audits */ - try { - $data = [ - '$collection' => 'buckets', - 'dateCreated' => \time(), - 'dateUpdated' => \time(), - 'name' => $name, - 'maximumFileSize' => $maximumFileSize, - 'allowedFileExtensions' => $allowedFileExtensions, - 'enabled' => $enabled, - 'adapter' => $adapter, - 'encryption' => $encryption, - 'antiVirus' => $antiVirus, - ]; + $data = [ + '$collection' => 'buckets', + 'dateCreated' => \time(), + 'dateUpdated' => \time(), + 'name' => $name, + 'maximumFileSize' => $maximumFileSize, + 'allowedFileExtensions' => $allowedFileExtensions, + 'enabled' => $enabled, + 'adapter' => $adapter, + 'encryption' => $encryption, + 'antiVirus' => $antiVirus, + ]; - $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user - $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; // By default set write permissions for user - $data = $dbForInternal->createDocument('buckets', new Document($data)); - } catch (AuthorizationException $exception) { - throw new Exception('Unauthorized permissions', 401); - } catch (StructureException $exception) { - throw new Exception('Bad structure. ' . $exception->getMessage(), 400); - } catch (\Exception$exception) { - throw new Exception('Failed saving document to DB', 500); - } + $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user + $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; // By default set write permissions for user + $data = $dbForInternal->createDocument('buckets', new Document($data)); $audits ->setParam('event', 'database.collections.create') From 491720183a922dc95b0b5f77588d543bb93c1f64 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:28:59 +0545 Subject: [PATCH 21/31] update descriptions --- app/controllers/api/storage.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index b97ab35e0d..bf0dd2582f 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -40,8 +40,8 @@ App::post('/v1/storage/buckets') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('name', '', new Text(128), 'Bucket name', false) - ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, 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', null, 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) ->param('maximumFileSize', 0, new Integer(), 'Maximum file size allowed.', true) ->param('allowedFileExtensions', ['*'], new ArrayList(new Text(64)), 'Allowed file extensions', true) ->param('enabled', true, new Boolean(), 'Is bucket enabled?', true) @@ -90,7 +90,7 @@ App::get('/v1/storage/buckets') ->desc('List buckets') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'storage') ->label('sdk.method', 'listBuckets') ->label('sdk.description', '/docs/references/storage/list-buckets.md') @@ -119,7 +119,7 @@ App::get('/v1/storage/buckets/:bucketId') ->desc('Get Bucket') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) ->label('sdk.namespace', 'storage') ->label('sdk.method', 'getBucket') ->label('sdk.description', '/docs/references/storage/get-bucket.md') From 1bf770ed3482156105ae1aa9d9eb84b4d8482fa0 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:35:40 +0545 Subject: [PATCH 22/31] moving storage buckets test to server scope --- .../Storage/StorageCustomServerTest.php | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 38bb3791be..3af737c454 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -5,10 +5,104 @@ namespace Tests\E2E\Services\Storage; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Tests\E2E\Client; class StorageCustomServerTest extends Scope { use StorageBase; use ProjectCustom; use SideServer; + + public function testCreateBucket():array + { + /** + * Test for SUCCESS + */ + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Test Bucket', + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + $this->assertNotEmpty($bucket['body']['$id']); + $this->assertIsInt($bucket['body']['dateCreated']); + $this->assertEquals('Test Bucket', $bucket['body']['name']); + $this->assertEquals(true, $bucket['body']['enabled']); + $bucketId = $bucket['body']['$id']; + /** + * Test for FAILURE + */ + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => '', + ]); + $this->assertEquals(400, $bucket['headers']['status-code']); + + return ['bucketId' => $bucketId]; + } + + /** + * @depends testCreateBucket + */ + public function testListBucket($data): array + { + $id = $data['bucketId'] ?? ''; + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertEquals($id, $response['body']['buckets'][0]['$id']); + $this->assertEquals('Test Bucket', $response['body']['buckets'][0]['name']); + + return $data; + } + + /** + * @depends testCreateBucket + */ + public function testGetBucket($data): array + { + $id = $data['bucketId'] ?? ''; + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $id, + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertEquals($id, $response['body']['$id']); + $this->assertEquals('Test Bucket', $response['body']['name']); + + /** + * Test for FAILURE + */ + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(400, $response['headers']['status-code']); + + return $data; + } } \ No newline at end of file From 928b083bcc4a9ed9a11db6311d211d8cb25cda30 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:35:54 +0545 Subject: [PATCH 23/31] updated to more in sync with collections --- app/controllers/api/storage.php | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index bf0dd2582f..27cc963567 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -23,8 +23,6 @@ use Appwrite\OpenSSL\OpenSSL; use Appwrite\Utopia\Response; use Utopia\Config\Config; use Utopia\Validator\Integer; -use Appwrite\Database\Exception\Authorization as AuthorizationException; -use Appwrite\Database\Exception\Structure as StructureException; use Utopia\Database\Query; App::post('/v1/storage/buckets') @@ -40,8 +38,8 @@ App::post('/v1/storage/buckets') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET) ->param('name', '', new Text(128), 'Bucket name', false) - ->param('read', null, 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', null, 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) + ->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) ->param('maximumFileSize', 0, new Integer(), 'Maximum file size allowed.', true) ->param('allowedFileExtensions', ['*'], new ArrayList(new Text(64)), 'Allowed file extensions', true) ->param('enabled', true, new Boolean(), 'Is bucket enabled?', true) @@ -59,7 +57,7 @@ App::post('/v1/storage/buckets') /** @var Appwrite\Database\Document $user */ /** @var Appwrite\Event\Event $audits */ - $data = [ + $data = $dbForInternal->createDocument('buckets', new Document([ '$collection' => 'buckets', 'dateCreated' => \time(), 'dateUpdated' => \time(), @@ -70,15 +68,13 @@ App::post('/v1/storage/buckets') 'adapter' => $adapter, 'encryption' => $encryption, 'antiVirus' => $antiVirus, - ]; - - $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user - $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; // By default set write permissions for user - $data = $dbForInternal->createDocument('buckets', new Document($data)); + '$read' => $read, + '$write' => $write, + ])); $audits - ->setParam('event', 'database.collections.create') - ->setParam('resource', 'database/collection/' . $data->getId()) + ->setParam('event', 'storage.buckets.create') + ->setParam('resource', 'storage/buckets/' . $data->getId()) ->setParam('data', $data->getArrayCopy()) ; From 7d5e073812b18f2167e51c86356a393355b35067 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:36:09 +0545 Subject: [PATCH 24/31] remove buckets test from base in favor for server side tests --- tests/e2e/Services/Storage/StorageBase.php | 93 ---------------------- 1 file changed, 93 deletions(-) diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 657bda16ea..508866b6a1 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -242,97 +242,4 @@ trait StorageBase return $data; } - - public function testCreateBucket():array - { - /** - * Test for SUCCESS - */ - $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'name' => 'Test Bucket', - ]); - $this->assertEquals(201, $bucket['headers']['status-code']); - $this->assertNotEmpty($bucket['body']['$id']); - $this->assertIsInt($bucket['body']['dateCreated']); - $this->assertEquals('Test Bucket', $bucket['body']['name']); - $this->assertEquals(true, $bucket['body']['enabled']); - $bucketId = $bucket['body']['$id']; - /** - * Test for FAILURE - */ - $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'name' => '', - ]); - $this->assertEquals(400, $bucket['headers']['status-code']); - - return ['bucketId' => $bucketId]; - } - - /** - * @depends testCreateBucket - */ - public function testListBucket($data): array - { - $id = $data['bucketId'] ?? ''; - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', - array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']); - $this->assertEquals($id, $response['body']['buckets'][0]['$id']); - $this->assertEquals('Test Bucket', $response['body']['buckets'][0]['name']); - - return $data; - } - - /** - * @depends testCreateBucket - */ - public function testGetBucket($data): array - { - $id = $data['bucketId'] ?? ''; - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $id, - array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']); - $this->assertEquals($id, $response['body']['$id']); - $this->assertEquals('Test Bucket', $response['body']['name']); - - /** - * Test for FAILURE - */ - - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty', - array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - $this->assertEquals(404, $response['headers']['status-code']); - - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', - array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - $this->assertEquals(400, $response['headers']['status-code']); - - return $data; - } } \ No newline at end of file From 30ec6fcaaea4b2fb3e3f158ae87f5f517abe24cf Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:39:19 +0545 Subject: [PATCH 25/31] create bucket validating all fields --- tests/e2e/Services/Storage/StorageCustomServerTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 3af737c454..87fa92836e 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -27,8 +27,14 @@ class StorageCustomServerTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); $this->assertIsInt($bucket['body']['dateCreated']); + $this->assertIsArray($bucket['body']['$read']); + $this->assertIsArray($bucket['body']['$write']); + $this->assertIsArray($bucket['body']['allowedFileExtensions']); $this->assertEquals('Test Bucket', $bucket['body']['name']); $this->assertEquals(true, $bucket['body']['enabled']); + $this->assertEquals(true, $bucket['body']['encryption']); + $this->assertEquals(true, $bucket['body']['antiVirus']); + $this->assertEquals('local', $bucket['body']['adapter']); $bucketId = $bucket['body']['$id']; /** * Test for FAILURE From 72ea5492fc9e172eabd056db425e0b4dcb106398 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:42:33 +0545 Subject: [PATCH 26/31] reference files --- docs/references/storage/create-bucket.md | 1 + docs/references/storage/get-bucket.md | 1 + docs/references/storage/list-buckets.md | 1 + 3 files changed, 3 insertions(+) create mode 100644 docs/references/storage/create-bucket.md create mode 100644 docs/references/storage/get-bucket.md create mode 100644 docs/references/storage/list-buckets.md diff --git a/docs/references/storage/create-bucket.md b/docs/references/storage/create-bucket.md new file mode 100644 index 0000000000..0ac8f1bf5b --- /dev/null +++ b/docs/references/storage/create-bucket.md @@ -0,0 +1 @@ +Create a new storage bucket. \ No newline at end of file diff --git a/docs/references/storage/get-bucket.md b/docs/references/storage/get-bucket.md new file mode 100644 index 0000000000..e0bd37ceac --- /dev/null +++ b/docs/references/storage/get-bucket.md @@ -0,0 +1 @@ +Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata. \ No newline at end of file diff --git a/docs/references/storage/list-buckets.md b/docs/references/storage/list-buckets.md new file mode 100644 index 0000000000..ed281ed277 --- /dev/null +++ b/docs/references/storage/list-buckets.md @@ -0,0 +1 @@ +Get a list of all the storage buckets. You can use the query params to filter your results. \ No newline at end of file From 9def955ab20d6edf00c86b806ffd17a2de8d3bee Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 11:52:35 +0545 Subject: [PATCH 27/31] bucket read scope --- tests/e2e/Scopes/ProjectCustom.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index dc5673ce83..b2324fc5d5 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -73,6 +73,7 @@ trait ProjectCustom 'documents.write', 'files.read', 'files.write', + 'buckets.read', 'buckets.write', 'functions.read', 'functions.write', From 7bb546ecb37eb3c8b31921d93b6642a394cc8281 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 12:52:05 +0545 Subject: [PATCH 28/31] Apply suggestions from code review Co-authored-by: Eldad A. Fux --- src/Appwrite/Utopia/Response/Model/Bucket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index cb1e1a5e16..c18d540685 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -39,7 +39,7 @@ class Bucket extends Model ]) ->addRule('dateUpdated', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Bucket updated date in Unix timestamp.', + 'description' => 'Bucket update date in Unix timestamp.', 'default' => 0, 'example' => 1592981250, ]) From 6c2117a7506dcf85f63b99428ffeec04bb22180b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 16 Jun 2021 13:25:49 +0545 Subject: [PATCH 29/31] removed extra whitespace --- app/controllers/api/storage.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 27cc963567..1ea0855919 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -138,7 +138,6 @@ App::get('/v1/storage/buckets/:bucketId') $response->dynamic2($bucket, Response::MODEL_BUCKET); }); - App::post('/v1/storage/files') ->desc('Create File') ->groups(['api', 'storage']) From 0c5072e8a43c9046f11f888720d084ac31bbb850 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 17 Jun 2021 11:13:27 +0545 Subject: [PATCH 30/31] Apply suggestions from code review Co-authored-by: Eldad A. Fux --- app/controllers/api/storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 1ea0855919..2191342102 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -131,7 +131,7 @@ App::get('/v1/storage/buckets/:bucketId') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if (empty($bucket->getId())) { + if ($bucket->isEmpty()) { throw new Exception('Bucket not found', 404); } From 67823a6e5d33d072022133d913a67acadc34a4b7 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 17 Jun 2021 12:27:29 +0545 Subject: [PATCH 31/31] webhook tests --- app/config/events.php | 5 +++ tests/e2e/Scopes/ProjectCustom.php | 1 + tests/e2e/Services/Webhooks/WebhooksBase.php | 35 ++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/app/config/events.php b/app/config/events.php index b27a5eafb9..18edf4ba4a 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -152,6 +152,11 @@ return [ 'model' => Response::MODEL_FILE, 'note' => '', ], + 'storage.buckets.create' => [ + 'description' => 'This event triggers when a storage bucket is created.', + 'model' => Response::MODEL_BUCKET, + 'note' => '', + ], 'users.create' => [ 'description' => 'This event triggers when a user is created from the users API.', 'model' => Response::MODEL_USER, diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index b2324fc5d5..53586162c5 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -126,6 +126,7 @@ trait ProjectCustom 'storage.files.create', 'storage.files.update', 'storage.files.delete', + 'storage.buckets.create', 'users.create', 'users.update.prefs', 'users.update.status', diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index dfbdc524c7..a6f3bc2785 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -552,4 +552,39 @@ trait WebhooksBase */ return []; } + + public function testCreateStorageBucket(): array + { + /** + * Test for SUCCESS + */ + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test Bucket', + ]); + + $this->assertEquals($bucket['headers']['status-code'], 201); + $this->assertNotEmpty($bucket['body']['$id']); + + $webhook = $this->getLastRequest(); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Event'], 'storage.buckets.create'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals('Test Bucket', $webhook['data']['name']); + $this->assertEquals(true, $webhook['data']['enabled']); + $this->assertIsArray($webhook['data']['$read']); + $this->assertIsArray($webhook['data']['$write']); + + return array_merge(['bucketId' => $bucket['body']['$id']]); + } } \ No newline at end of file