Merge branch 'feat-storage-buckets' into feat-sb-delete
This commit is contained in:
commit
e0faaf2758
4 changed files with 49 additions and 22 deletions
|
@ -222,6 +222,17 @@ App::post('/v1/storage/buckets')
|
||||||
'array' => false,
|
'array' => false,
|
||||||
'filters' => [],
|
'filters' => [],
|
||||||
]),
|
]),
|
||||||
|
new Document([
|
||||||
|
'$id' => 'search',
|
||||||
|
'type' => Database::VAR_STRING,
|
||||||
|
'format' => '',
|
||||||
|
'size' => 16384,
|
||||||
|
'signed' => true,
|
||||||
|
'required' => false,
|
||||||
|
'default' => null,
|
||||||
|
'array' => false,
|
||||||
|
'filters' => [],
|
||||||
|
]),
|
||||||
], [
|
], [
|
||||||
new Document([
|
new Document([
|
||||||
'$id' => '_key_bucket',
|
'$id' => '_key_bucket',
|
||||||
|
@ -231,12 +242,12 @@ App::post('/v1/storage/buckets')
|
||||||
'orders' => [Database::ORDER_ASC],
|
'orders' => [Database::ORDER_ASC],
|
||||||
]),
|
]),
|
||||||
new Document([
|
new Document([
|
||||||
'$id' => '_fulltext_name',
|
'$id' => '_key_search',
|
||||||
'type' => Database::INDEX_FULLTEXT,
|
'type' => Database::INDEX_FULLTEXT,
|
||||||
'attributes' => ['name'],
|
'attributes' => ['search'],
|
||||||
'lengths' => [1024],
|
'lengths' => [2048],
|
||||||
'orders' => [Database::ORDER_ASC],
|
'orders' => [Database::ORDER_ASC],
|
||||||
]),
|
],),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$bucket = $dbForInternal->createDocument('buckets', new Document([
|
$bucket = $dbForInternal->createDocument('buckets', new Document([
|
||||||
|
@ -244,7 +255,7 @@ App::post('/v1/storage/buckets')
|
||||||
'$collection' => 'buckets',
|
'$collection' => 'buckets',
|
||||||
'dateCreated' => \time(),
|
'dateCreated' => \time(),
|
||||||
'dateUpdated' => \time(),
|
'dateUpdated' => \time(),
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'permission' => $permission,
|
'permission' => $permission,
|
||||||
'maximumFileSize' => $maximumFileSize,
|
'maximumFileSize' => $maximumFileSize,
|
||||||
'allowedFileExtensions' => $allowedFileExtensions,
|
'allowedFileExtensions' => $allowedFileExtensions,
|
||||||
|
@ -252,8 +263,8 @@ App::post('/v1/storage/buckets')
|
||||||
'adapter' => $adapter,
|
'adapter' => $adapter,
|
||||||
'encryption' => $encryption,
|
'encryption' => $encryption,
|
||||||
'antiVirus' => $antiVirus,
|
'antiVirus' => $antiVirus,
|
||||||
'$read' => $read,
|
'$read' => $read ?? [],
|
||||||
'$write' => $write,
|
'$write' => $write ?? [],
|
||||||
'search' => implode(' ', [$bucketId, $name]),
|
'search' => implode(' ', [$bucketId, $name]),
|
||||||
]));
|
]));
|
||||||
} catch (Duplicate $th) {
|
} catch (Duplicate $th) {
|
||||||
|
@ -286,30 +297,31 @@ App::get('/v1/storage/buckets')
|
||||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
->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('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('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('cursor', '', 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('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForInternal')
|
->inject('dbForInternal')
|
||||||
->inject('usage')
|
->inject('usage')
|
||||||
->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal, $usage) {
|
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal, $usage) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Utopia\Database\Database $dbForInternal */
|
/** @var Utopia\Database\Database $dbForInternal */
|
||||||
/** @var Appwrite\Stats\Stats $usage */
|
/** @var Appwrite\Stats\Stats $usage */
|
||||||
|
|
||||||
$queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : [];
|
$queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : [];
|
||||||
|
|
||||||
if (!empty($after)) {
|
if (!empty($cursor)) {
|
||||||
$afterBucket = $dbForInternal->getDocument('buckets', $after);
|
$cursorBucket = $dbForInternal->getDocument('buckets', $cursor);
|
||||||
|
|
||||||
if ($afterBucket->isEmpty()) {
|
if ($cursorBucket->isEmpty()) {
|
||||||
throw new Exception("Bucket '{$after}' for the 'after' value not found.", 400);
|
throw new Exception("Bucket '{$cursor}' for the 'cursor' value not found.", 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$usage->setParam('storage.buckets.read', 1);
|
$usage->setParam('storage.buckets.read', 1);
|
||||||
|
|
||||||
$response->dynamic(new Document([
|
$response->dynamic(new Document([
|
||||||
'buckets' => $dbForInternal->find('buckets', $queries, $limit, $offset, [], [$orderType], $afterBucket ?? null),
|
'buckets' => $dbForInternal->find('buckets', $queries, $limit, $offset, [], [$orderType], $cursorBucket ?? null, $cursorDirection),
|
||||||
'sum' => $dbForInternal->count('buckets', $queries, APP_LIMIT_COUNT),
|
'sum' => $dbForInternal->count('buckets', $queries, APP_LIMIT_COUNT),
|
||||||
]), Response::MODEL_BUCKET_LIST);
|
]), Response::MODEL_BUCKET_LIST);
|
||||||
});
|
});
|
||||||
|
@ -654,7 +666,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForInternal')
|
->inject('dbForInternal')
|
||||||
->inject('usage')
|
->inject('usage')
|
||||||
->action(function ($bucketId, $search, $limit, $offset, $after, $orderType, $response, $dbForInternal, $usage) {
|
->action(function ($bucketId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal, $usage) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Utopia\Database\Database $dbForInternal */
|
/** @var Utopia\Database\Database $dbForInternal */
|
||||||
/** @var Appwrite\Stats\Stats $usage */
|
/** @var Appwrite\Stats\Stats $usage */
|
||||||
|
@ -671,11 +683,11 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
||||||
$queries[] = [new Query('name', Query::TYPE_SEARCH, [$search])];
|
$queries[] = [new Query('name', Query::TYPE_SEARCH, [$search])];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($after)) {
|
if (!empty($cursor)) {
|
||||||
$afterFile = $dbForInternal->getDocument('bucket_' . $bucketId, $after);
|
$cursorFile = $dbForInternal->getDocument('bucket_' . $bucketId, $cursor);
|
||||||
|
|
||||||
if ($afterFile->isEmpty()) {
|
if ($cursorFile->isEmpty()) {
|
||||||
throw new Exception("File '{$after}' for the 'after' value not found.", 400);
|
throw new Exception("File '{$cursor}' for the 'cursor' value not found.", 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +703,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->dynamic(new Document([
|
$response->dynamic(new Document([
|
||||||
'files' => $dbForInternal->find('bucket_' . $bucketId, $queries, $limit, $offset, [], [$orderType], $afterFile ?? null),
|
'files' => $dbForInternal->find('bucket_' . $bucketId, $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection),
|
||||||
'sum' => $dbForInternal->count('bucket_' . $bucketId, $queries, APP_LIMIT_COUNT),
|
'sum' => $dbForInternal->count('bucket_' . $bucketId, $queries, APP_LIMIT_COUNT),
|
||||||
]), Response::MODEL_FILE_LIST);
|
]), Response::MODEL_FILE_LIST);
|
||||||
});
|
});
|
||||||
|
|
|
@ -53,6 +53,7 @@ class StorageConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'bucketId' => 'unique()',
|
'bucketId' => 'unique()',
|
||||||
'name' => 'Test Bucket',
|
'name' => 'Test Bucket',
|
||||||
|
'permission' => 'file'
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(201, $bucket['headers']['status-code']);
|
$this->assertEquals(201, $bucket['headers']['status-code']);
|
||||||
$bucketId = $bucket['body']['$id'];
|
$bucketId = $bucket['body']['$id'];
|
||||||
|
|
|
@ -19,7 +19,21 @@ class StorageCustomClientTest extends Scope
|
||||||
/**
|
/**
|
||||||
* Test for SUCCESS
|
* Test for SUCCESS
|
||||||
*/
|
*/
|
||||||
$file = $this->client->call(Client::METHOD_POST, '/storage/files', array_merge([
|
$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'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'bucketId' => 'unique()',
|
||||||
|
'name' => 'Test Bucket',
|
||||||
|
'permission' => 'file',
|
||||||
|
'read' => ['role:all'],
|
||||||
|
'write' => ['role:all'],
|
||||||
|
]);
|
||||||
|
$this->assertEquals(201, $bucket['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($bucket['body']['$id']);
|
||||||
|
|
||||||
|
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'. $bucket['body']['$id'] . '/files', array_merge([
|
||||||
'content-type' => 'multipart/form-data',
|
'content-type' => 'multipart/form-data',
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
|
|
|
@ -92,7 +92,7 @@ class StorageCustomServerTest extends Scope
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'after' => $response['body']['buckets'][0]['$id']
|
'cursor' => $response['body']['buckets'][0]['$id']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
|
Loading…
Reference in a new issue