mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #8968 from appwrite/feat-bulk-create
Feat: Bulk Create Documents
This commit is contained in:
commit
8c1f6aabb7
12 changed files with 747 additions and 121 deletions
|
|
@ -4620,6 +4620,14 @@
|
|||
"description": "Document data as JSON object.",
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -4628,11 +4636,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8189,6 +8189,14 @@
|
|||
"description": "Document data as JSON object.",
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -8197,11 +8205,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7718,6 +7718,14 @@
|
|||
"description": "Document data as JSON object.",
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -7726,11 +7734,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4776,15 +4776,24 @@
|
|||
"documentId": {
|
||||
"type": "string",
|
||||
"description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.",
|
||||
"default": null,
|
||||
"default": "",
|
||||
"x-example": "<DOCUMENT_ID>"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Document data as JSON object.",
|
||||
"default": {},
|
||||
"default": [],
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"default": [],
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -4794,11 +4803,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8332,15 +8332,24 @@
|
|||
"documentId": {
|
||||
"type": "string",
|
||||
"description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.",
|
||||
"default": null,
|
||||
"default": "",
|
||||
"x-example": "<DOCUMENT_ID>"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Document data as JSON object.",
|
||||
"default": {},
|
||||
"default": [],
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"default": [],
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -8350,11 +8359,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7848,15 +7848,24 @@
|
|||
"documentId": {
|
||||
"type": "string",
|
||||
"description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.",
|
||||
"default": null,
|
||||
"default": "",
|
||||
"x-example": "<DOCUMENT_ID>"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Document data as JSON object.",
|
||||
"default": {},
|
||||
"default": [],
|
||||
"x-example": "{}"
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"description": "Array of documents data as JSON object.",
|
||||
"default": [],
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
|
|
@ -7866,11 +7875,7 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documentId",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2845,7 +2845,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default'])
|
||||
->desc('Create document')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create')
|
||||
->label('scope', 'documents.write')
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'document.create')
|
||||
|
|
@ -2863,26 +2862,41 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents')
|
||||
->label('sdk.offline.key', '{documentId}')
|
||||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', true)
|
||||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
|
||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||
->param('data', [], new JSON(), 'Document data as JSON object.', true)
|
||||
->param('documents', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_DOCUMENTS_SIZE), 'Array of documents data as JSON object.', true)
|
||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('user')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForUsage')
|
||||
->inject('project')
|
||||
->inject('mode')
|
||||
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode) {
|
||||
|
||||
->action(function (string $databaseId, ?string $documentId, string $collectionId, string|array|null $data, ?array $documents, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, Document $project, string $mode) {
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
$isBulk = true;
|
||||
|
||||
if (empty($data)) {
|
||||
if (empty($data) && empty($documents)) {
|
||||
throw new Exception(Exception::DOCUMENT_MISSING_DATA);
|
||||
}
|
||||
|
||||
if (isset($data['$id'])) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead');
|
||||
if (!empty($data) && !empty($documents)) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'You can only send one of the following parameters: data, documents');
|
||||
}
|
||||
|
||||
if (!empty($data) && empty($documentId)) {
|
||||
throw new Exception(Exception::DOCUMENT_MISSING_DATA, 'Document ID is required when creating a single document');
|
||||
}
|
||||
|
||||
if (!empty($documents) && !empty($documentId)) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Param "documentId" is disallowed when creating multiple documents, use $id inside the documents');
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$isBulk = false;
|
||||
$documents = [$data];
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
|
@ -2906,43 +2920,46 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
Database::PERMISSION_DELETE,
|
||||
];
|
||||
|
||||
// Map aggregate permissions to into the set of individual permissions they represent.
|
||||
$permissions = Permission::aggregate($permissions, $allowedPermissions);
|
||||
|
||||
// Add permissions for current the user if none were provided.
|
||||
if (\is_null($permissions)) {
|
||||
$permissions = [];
|
||||
if (!empty($user->getId())) {
|
||||
foreach ($allowedPermissions as $permission) {
|
||||
$permissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
|
||||
}
|
||||
$setPermissions = function (Document $document, ?array $permissions) use ($user, $allowedPermissions, $isAPIKey, $isPrivilegedUser, $isBulk) {
|
||||
// Map aggregate permissions to into the set of individual permissions they represent.
|
||||
if ($isBulk) {
|
||||
$permissions = $document['$permissions'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
// Users can only manage their own roles, API keys and Admin users can manage any
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
foreach (Database::PERMISSIONS as $type) {
|
||||
foreach ($permissions as $permission) {
|
||||
$permission = Permission::parse($permission);
|
||||
if ($permission->getPermission() != $type) {
|
||||
continue;
|
||||
}
|
||||
$role = (new Role(
|
||||
$permission->getRole(),
|
||||
$permission->getIdentifier(),
|
||||
$permission->getDimension()
|
||||
))->toString();
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')');
|
||||
$permissions = Permission::aggregate($permissions, $allowedPermissions);
|
||||
|
||||
// Add permissions for current the user if none were provided.
|
||||
if (\is_null($permissions)) {
|
||||
$permissions = [];
|
||||
if (!empty($user->getId())) {
|
||||
foreach ($allowedPermissions as $permission) {
|
||||
$permissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers
|
||||
$data['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId;
|
||||
$data['$permissions'] = $permissions;
|
||||
$document = new Document($data);
|
||||
// Users can only manage their own roles, API keys and Admin users can manage any
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
foreach (Database::PERMISSIONS as $type) {
|
||||
foreach ($permissions as $permission) {
|
||||
$permission = Permission::parse($permission);
|
||||
if ($permission->getPermission() != $type) {
|
||||
continue;
|
||||
}
|
||||
$role = (new Role(
|
||||
$permission->getRole(),
|
||||
$permission->getIdentifier(),
|
||||
$permission->getDimension()
|
||||
))->toString();
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$document->setAttribute('$permissions', $permissions);
|
||||
};
|
||||
|
||||
$checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database) {
|
||||
$documentSecurity = $collection->getAttribute('documentSecurity', false);
|
||||
|
|
@ -3024,10 +3041,29 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
}
|
||||
};
|
||||
|
||||
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
|
||||
$documents = array_map(function ($document) use ($collection, $permissions, $checkPermissions, $isBulk, $documentId, $setPermissions) {
|
||||
$document['$collection'] = $collection->getId();
|
||||
|
||||
if (!$isBulk) {
|
||||
$document['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId;
|
||||
} else {
|
||||
if (empty($document['$id'])) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is required inside documents when creating bulk documents');
|
||||
}
|
||||
|
||||
$document['$id'] = $document['$id'] == 'unique()' ? ID::unique() : $document['$id'];
|
||||
}
|
||||
|
||||
$document = new Document($document);
|
||||
|
||||
$setPermissions($document, $permissions);
|
||||
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
|
||||
|
||||
return $document;
|
||||
}, $documents);
|
||||
|
||||
try {
|
||||
$document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document);
|
||||
$dbForProject->createDocuments('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documents);
|
||||
} catch (StructureException $e) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
|
||||
} catch (DuplicateException $e) {
|
||||
|
|
@ -3036,8 +3072,15 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
->setParam('databaseId', $databaseId)
|
||||
->setParam('collectionId', $collection->getId())
|
||||
->setContext('collection', $collection)
|
||||
->setContext('database', $database);
|
||||
|
||||
// Add $collectionId and $databaseId for all documents
|
||||
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
|
||||
$processDocument = function (Document $collection, Document &$document) use (&$processDocument, $dbForProject, $database) {
|
||||
$document->removeAttribute('$collection');
|
||||
$document->setAttribute('$databaseId', $database->getId());
|
||||
$document->setAttribute('$collectionId', $collection->getId());
|
||||
|
||||
|
|
@ -3069,28 +3112,26 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
}
|
||||
};
|
||||
|
||||
$processDocument($collection, $document);
|
||||
foreach ($documents as $document) {
|
||||
$processDocument($collection, $document);
|
||||
}
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($document, Response::MODEL_DOCUMENT);
|
||||
|
||||
$relationships = \array_map(
|
||||
fn ($document) => $document->getAttribute('key'),
|
||||
\array_filter(
|
||||
$collection->getAttribute('attributes', []),
|
||||
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
|
||||
)
|
||||
);
|
||||
|
||||
$queueForEvents
|
||||
->setParam('databaseId', $databaseId)
|
||||
->setParam('collectionId', $collection->getId())
|
||||
->setParam('documentId', $document->getId())
|
||||
->setContext('collection', $collection)
|
||||
->setContext('database', $database)
|
||||
->setPayload($response->getPayload(), sensitive: $relationships);
|
||||
if ($isBulk) {
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic(new Document([
|
||||
'total' => count($documents),
|
||||
'documents' => $documents
|
||||
]), Response::MODEL_DOCUMENT_LIST);
|
||||
} else {
|
||||
$queueForEvents
|
||||
->setParam('documentId', $document->getId())
|
||||
->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create');
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($documents[0], Response::MODEL_DOCUMENT);
|
||||
}
|
||||
|
||||
$queueForUsage
|
||||
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
|
||||
|
|
@ -3173,7 +3214,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
return false;
|
||||
}
|
||||
|
||||
$document->removeAttribute('$collection');
|
||||
$document->setAttribute('$databaseId', $database->getId());
|
||||
$document->setAttribute('$collectionId', $collection->getId());
|
||||
|
||||
|
|
|
|||
|
|
@ -503,6 +503,7 @@ App::init()
|
|||
|
||||
$dbForProject
|
||||
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage))
|
||||
->on(Database::EVENT_DOCUMENTS_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage))
|
||||
->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage))
|
||||
->on(Database::EVENT_DOCUMENT_CREATE, 'create-trigger-events', fn ($event, $document) => $eventDatabaseListener(
|
||||
$document,
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ const APP_LIMIT_COMPRESSION = 20_000_000; //20MB
|
|||
const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value
|
||||
const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value
|
||||
const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length.
|
||||
const APP_LIMIT_ARRAY_DOCUMENTS_SIZE = 10_000; // Default maximum of how many documents can be inserted in a single request
|
||||
const APP_LIMIT_SUBQUERY = 1000;
|
||||
const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
|
||||
const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period
|
||||
|
|
|
|||
32
tests/benchmarks/bulk-operations.js
Normal file
32
tests/benchmarks/bulk-operations.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { check } from "k6";
|
||||
import http from "k6/http";
|
||||
|
||||
const amount = 100_000;
|
||||
const databaseId = "674918b20017411b94b2";
|
||||
const collectionId = "674918b4002b46c47d5d";
|
||||
|
||||
const documents = Array(amount).fill({
|
||||
$id: "unique()",
|
||||
name: "asd",
|
||||
});
|
||||
|
||||
export default function () {
|
||||
const payload = JSON.stringify({
|
||||
documents,
|
||||
});
|
||||
|
||||
const res = http.post(`http://localhost/v1/databases/${databaseId}/collections/${collectionId}/documents`,
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
"X-Appwrite-Key": "standard_fa89c4834660f39e95ca2c2996fe7dd4ff498725e37c09323234c009570c1719f1c10610bf3541cf9ead120c107e41397a4eae1c787c83bdf577857bbc5963341641c77f582cc41e11a0d50eb4c2e4b1fda74418a8b9a253d6e63008e33560ba35310b9dc2fed5f09ca599e646f744cc6308b8ccd27ff04f9e498ec5a5f2c3db",
|
||||
"X-Appwrite-Project": "674818bc0017934d58dd",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
check(res, {
|
||||
"status is 200": (r) => r.status === 201,
|
||||
});
|
||||
}
|
||||
|
|
@ -4800,6 +4800,310 @@ trait DatabasesBase
|
|||
]));
|
||||
}
|
||||
|
||||
public function testBulkCreate(): void
|
||||
{
|
||||
// Create database
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Bulk Create Perms',
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($database['body']['$id']);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Bulk Create Perms',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::any()),
|
||||
Permission::read(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
|
||||
$data = [
|
||||
'$id' => $collection['body']['$id'],
|
||||
'databaseId' => $collection['body']['databaseId']
|
||||
];
|
||||
|
||||
// Await attribute
|
||||
$numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['$id'] . '/attributes/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'number',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 2,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 3,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertCount(3, $response['body']['documents']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(3, $response['body']['documents']);
|
||||
|
||||
// TEST FAIL - Can't use data and document together
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'number' => 5
|
||||
],
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals('You can only send one of the following parameters: data, documents', $response['body']['message']);
|
||||
|
||||
// TEST FAIL - Can't use $documentId and create bulk documents
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// TEST FAIL - Can't miss $id in bulk documents
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'number' => 1,
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals('$id is required inside documents when creating bulk documents', $response['body']['message']);
|
||||
|
||||
// TEST FAIL - Can't miss number in bulk documents
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// TEST FAIL - Can't push more than 10000 documents
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => array_fill(0, 10001, [
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
]),
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals('Invalid `documents` param: Value must a valid array no longer than 10000 items and Value must be a valid JSON string', $response['body']['message']);
|
||||
}
|
||||
|
||||
public function testBulkCreateRelationships(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Bulk Creates Relationships'
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($database['body']['$id']);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Collection1',
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::any()),
|
||||
Permission::read(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
]);
|
||||
|
||||
$collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Collection2',
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::any()),
|
||||
Permission::read(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
]);
|
||||
|
||||
$collection1 = $collection1['body']['$id'];
|
||||
$collection2 = $collection2['body']['$id'];
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2,
|
||||
'type' => Database::RELATION_ONE_TO_MANY,
|
||||
'key' => 'collection2',
|
||||
'onDelete' => Database::RELATION_MUTATE_RESTRICT,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2 . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(3);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collection1}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 1',
|
||||
'collection2' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 2',
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 3',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 2',
|
||||
'collection2' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 4',
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Document 5',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertCount(2, $response['body']['documents']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collection1}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, $response['body']['total']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collection2}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(4, $response['body']['total']);
|
||||
}
|
||||
|
||||
public function testBulkDeletes(): void
|
||||
{
|
||||
// Create database
|
||||
|
|
@ -4855,19 +5159,23 @@ trait DatabasesBase
|
|||
|
||||
// Create documents
|
||||
$createBulkDocuments = function ($amount = 10) use ($data) {
|
||||
for ($x = 0; $x <= $amount; $x++) {
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'number' => $x,
|
||||
],
|
||||
]);
|
||||
$documents = [];
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
for ($x = 0; $x <= $amount; $x++) {
|
||||
$documents[] = [
|
||||
'$id' => ID::unique(),
|
||||
'number' => $x,
|
||||
];
|
||||
}
|
||||
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => $documents,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
};
|
||||
|
||||
$createBulkDocuments();
|
||||
|
|
@ -5503,19 +5811,23 @@ trait DatabasesBase
|
|||
|
||||
// Create documents
|
||||
$createBulkDocuments = function ($amount = 10) use ($data) {
|
||||
for ($x = 1; $x <= $amount; $x++) {
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'number' => $x,
|
||||
],
|
||||
]);
|
||||
$documents = [];
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
for ($x = 1; $x <= $amount; $x++) {
|
||||
$documents[] = [
|
||||
'$id' => ID::unique(),
|
||||
'number' => $x,
|
||||
];
|
||||
}
|
||||
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => $documents,
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
};
|
||||
|
||||
$createBulkDocuments();
|
||||
|
|
|
|||
|
|
@ -892,6 +892,219 @@ class DatabasesCustomClientTest extends Scope
|
|||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testBulkCreatePermissions(): void
|
||||
{
|
||||
// Create database
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Bulk Create'
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($database['body']['$id']);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Bulk Create',
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
|
||||
|
||||
$data = [
|
||||
'$id' => $collection['body']['$id'],
|
||||
'databaseId' => $collection['body']['databaseId']
|
||||
];
|
||||
|
||||
// Await attribute
|
||||
$numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['$id'] . '/attributes/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'number',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// TEST FAIL - Can't create document with missing collection level permissions
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 2,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 3,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
$this->assertEquals('The current user is not authorized to perform the requested action.', $response['body']['message']);
|
||||
|
||||
// TEST FAIL - Can't create document with missing document level permissions
|
||||
$collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'name' => 'Bulk Creates Perms',
|
||||
'documentSecurity' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collection['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 2,
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 3,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
$this->assertEquals('The current user is not authorized to perform the requested action.', $response['body']['message']);
|
||||
|
||||
// TEST FAIL - Can't create document with permissions that aren't our own.
|
||||
$collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'name' => 'Bulk Creates Perms',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collection['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user('aaaaaa')),
|
||||
Permission::read(Role::user('aaaaaa')),
|
||||
Permission::update(Role::user('aaaaaa')),
|
||||
Permission::delete(Role::user('aaaaaa')),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 2,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user('aaaaaa')),
|
||||
Permission::read(Role::user('aaaaaa')),
|
||||
Permission::update(Role::user('aaaaaa')),
|
||||
Permission::delete(Role::user('aaaaaa')),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 3,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user('aaaaaa')),
|
||||
Permission::read(Role::user('aaaaaa')),
|
||||
Permission::update(Role::user('aaaaaa')),
|
||||
Permission::delete(Role::user('aaaaaa')),
|
||||
]
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// TEST SUCCESS - Can create document with our own permissions.
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 1,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 2,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'number' => 3,
|
||||
'$permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertCount(3, $response['body']['documents']);
|
||||
}
|
||||
|
||||
// Bulk Updates
|
||||
public function testBulkUpdatesPermissions(): void
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue