Merge pull request #5887 from appwrite/fix-5404-update-document-without-relation-permission
Fix 5404 update document without relation permission
This commit is contained in:
commit
a019d01e91
|
@ -196,16 +196,14 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
|||
->setType(DATABASE_TYPE_CREATE_ATTRIBUTE)
|
||||
->setDatabase($db)
|
||||
->setCollection($collection)
|
||||
->setDocument($attribute)
|
||||
;
|
||||
->setDocument($attribute);
|
||||
|
||||
$events
|
||||
->setContext('collection', $collection)
|
||||
->setContext('database', $db)
|
||||
->setParam('databaseId', $databaseId)
|
||||
->setParam('collectionId', $collection->getId())
|
||||
->setParam('attributeId', $attribute->getId())
|
||||
;
|
||||
->setParam('attributeId', $attribute->getId());
|
||||
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
|
||||
|
@ -682,13 +680,11 @@ App::delete('/v1/databases/:databaseId')
|
|||
|
||||
$deletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($database)
|
||||
;
|
||||
->setDocument($database);
|
||||
|
||||
$events
|
||||
->setParam('databaseId', $database->getId())
|
||||
->setPayload($response->output($database, Response::MODEL_DATABASE))
|
||||
;
|
||||
->setPayload($response->output($database, Response::MODEL_DATABASE));
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
@ -3250,28 +3246,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
}
|
||||
|
||||
$data = \array_merge($document->getArrayCopy(), $data); // Merge existing data with new data
|
||||
$data['$collection'] = $collection->getId(); // Make sure user doesn't switch collectionID
|
||||
$data['$collection'] = $document->getAttribute('$collection'); // Make sure user doesn't switch collectionID
|
||||
$data['$createdAt'] = $document->getCreatedAt(); // Make sure user doesn't switch createdAt
|
||||
$data['$id'] = $document->getId(); // Make sure user doesn't switch document unique ID
|
||||
$data['$permissions'] = $permissions;
|
||||
$newDocument = new Document($data);
|
||||
|
||||
$checkPermissions = function (Document $collection, Document $document, Document $old, string $permission) use (&$checkPermissions, $dbForProject, $database) {
|
||||
$documentSecurity = $collection->getAttribute('documentSecurity', false);
|
||||
$validator = new Authorization($permission);
|
||||
|
||||
$valid = $validator->isValid($collection->getPermissionsByType($permission));
|
||||
if (!$documentSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($permission === Database::PERMISSION_UPDATE) {
|
||||
$valid = $valid || $validator->isValid($old->getPermissionsByType($permission));
|
||||
if ($documentSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
$setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) {
|
||||
$relationships = \array_filter(
|
||||
$collection->getAttribute('attributes', []),
|
||||
fn($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
|
||||
|
@ -3298,6 +3279,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
);
|
||||
|
||||
foreach ($relations as &$relation) {
|
||||
// If the relation is an array it can be either update or create a child document.
|
||||
if (
|
||||
\is_array($relation)
|
||||
&& \array_values($relation) !== $relation
|
||||
|
@ -3311,21 +3293,20 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(),
|
||||
$relation->getId()
|
||||
));
|
||||
$relation->removeAttribute('$collectionId');
|
||||
$relation->removeAttribute('$databaseId');
|
||||
// Attribute $collection is required for Utopia.
|
||||
$relation->setAttribute(
|
||||
'$collection',
|
||||
'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()
|
||||
);
|
||||
|
||||
if ($oldDocument->isEmpty()) {
|
||||
$type = Database::PERMISSION_CREATE;
|
||||
|
||||
if (isset($relation['$id']) && $relation['$id'] === 'unique()') {
|
||||
$relation['$id'] = ID::unique();
|
||||
}
|
||||
} else {
|
||||
$relation->removeAttribute('$collectionId');
|
||||
$relation->removeAttribute('$databaseId');
|
||||
$relation->setAttribute('$collection', $relatedCollection->getId());
|
||||
$type = Database::PERMISSION_UPDATE;
|
||||
}
|
||||
|
||||
$checkPermissions($relatedCollection, $relation, $oldDocument, $type);
|
||||
$setCollection($relatedCollection, $relation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3335,26 +3316,26 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
$document->setAttribute($relationship->getAttribute('key'), \reset($relations));
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
$checkPermissions($collection, $newDocument, $document, Database::PERMISSION_UPDATE);
|
||||
$setCollection($collection, $newDocument);
|
||||
|
||||
try {
|
||||
$document = $dbForProject->withRequestTimestamp(
|
||||
$requestTimestamp,
|
||||
fn() => $dbForProject->updateDocument(
|
||||
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
|
||||
$document->getId(),
|
||||
$newDocument
|
||||
)
|
||||
);
|
||||
} catch (AuthorizationException) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
}
|
||||
try {
|
||||
$document = $dbForProject->withRequestTimestamp(
|
||||
$requestTimestamp,
|
||||
fn() => $dbForProject->updateDocument(
|
||||
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
|
||||
$document->getId(),
|
||||
$newDocument
|
||||
)
|
||||
);
|
||||
} catch (AuthorizationException) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
}
|
||||
|
||||
// Add $collectionId and $databaseId for all documents
|
||||
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
|
||||
|
|
36
composer.lock
generated
36
composer.lock
generated
|
@ -1516,16 +1516,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.42.0",
|
||||
"version": "0.42.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "5631f151ce2b454517f11c1914e50a1fa70c7bd1"
|
||||
"reference": "9ff69a9b9eadc581771798833d423829c9d8cc90"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/5631f151ce2b454517f11c1914e50a1fa70c7bd1",
|
||||
"reference": "5631f151ce2b454517f11c1914e50a1fa70c7bd1",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/9ff69a9b9eadc581771798833d423829c9d8cc90",
|
||||
"reference": "9ff69a9b9eadc581771798833d423829c9d8cc90",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1566,9 +1566,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.42.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.42.1"
|
||||
},
|
||||
"time": "2023-08-10T23:18:38+00:00"
|
||||
"time": "2023-08-14T16:09:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
@ -2993,16 +2993,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.16.0",
|
||||
"version": "v4.17.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "19526a33fb561ef417e822e85f08a00db4059c17"
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
|
||||
"reference": "19526a33fb561ef417e822e85f08a00db4059c17",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3043,9 +3043,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
|
||||
},
|
||||
"time": "2023-06-25T14:52:30+00:00"
|
||||
"time": "2023-08-13T19:53:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
|
@ -3270,16 +3270,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "1.7.2",
|
||||
"version": "1.7.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "b2fe4d22a5426f38e014855322200b97b5362c0d"
|
||||
"reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d",
|
||||
"reference": "b2fe4d22a5426f38e014855322200b97b5362c0d",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419",
|
||||
"reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3322,9 +3322,9 @@
|
|||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2"
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3"
|
||||
},
|
||||
"time": "2023-05-30T18:13:47+00:00"
|
||||
"time": "2023-08-12T11:01:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
|
|
|
@ -316,4 +316,420 @@ class DatabasesCustomClientTest extends Scope
|
|||
$this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']);
|
||||
$this->assertEquals('restrict', $collection1RelationAttribute['onDelete']);
|
||||
}
|
||||
|
||||
public function testUpdateWithoutRelationPermission(): void
|
||||
{
|
||||
$userId = $this->getUser()['$id'];
|
||||
$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' => ID::unique(),
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Creating collection 1
|
||||
$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::custom('collection1'),
|
||||
'name' => ID::custom('collection1'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
// Creating collection 2
|
||||
$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::custom('collection2'),
|
||||
'name' => ID::custom('collection2'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
$collection3 = $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::custom('collection3'),
|
||||
'name' => ID::custom('collection3'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
$collection4 = $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::custom('collection4'),
|
||||
'name' => ID::custom('collection4'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
$collection5 = $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::custom('collection5'),
|
||||
'name' => ID::custom('collection5'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
// Creating one to one relationship from collection 1 to colletion 2
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => 'oneToOne',
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => $collection2['body']['$id']
|
||||
]);
|
||||
|
||||
// Creating one to one relationship from collection 2 to colletion 3
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection3['body']['$id'],
|
||||
'type' => 'oneToOne',
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => $collection3['body']['$id']
|
||||
]);
|
||||
|
||||
// Creating one to one relationship from collection 3 to colletion 4
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection4['body']['$id'],
|
||||
'type' => 'oneToOne',
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => $collection4['body']['$id']
|
||||
]);
|
||||
|
||||
// Creating one to one relationship from collection 4 to colletion 5
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection5['body']['$id'],
|
||||
'type' => 'oneToOne',
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => $collection5['body']['$id']
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => "Title",
|
||||
'size' => 100,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => "Rating",
|
||||
'size' => 100,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => "Rating",
|
||||
'size' => 100,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection4['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => "Rating",
|
||||
'size' => 100,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection5['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => "Rating",
|
||||
'size' => 100,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Creating parent document with a child reference to test the permissions
|
||||
$parentDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => ID::custom($collection1['body']['$id']),
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => ID::custom($collection2['body']['$id']),
|
||||
'Rating' => '10',
|
||||
$collection3['body']['$id'] => [
|
||||
'$id' => ID::custom($collection3['body']['$id']),
|
||||
'Rating' => '10',
|
||||
$collection4['body']['$id'] => [
|
||||
'$id' => ID::custom($collection4['body']['$id']),
|
||||
'Rating' => '10',
|
||||
$collection5['body']['$id'] => [
|
||||
'$id' => ID::custom($collection5['body']['$id']),
|
||||
'Rating' => '10'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $parentDocument['headers']['status-code']);
|
||||
// This is the point of the test. We should not need any authorization permission to update the document with same data.
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::custom($collection1['body']['$id']),
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => $collection2['body']['$id'],
|
||||
'Rating' => '10',
|
||||
$collection3['body']['$id'] => [
|
||||
'$id' => $collection3['body']['$id'],
|
||||
'Rating' => '10',
|
||||
$collection4['body']['$id'] => [
|
||||
'$id' => $collection4['body']['$id'],
|
||||
'Rating' => '10',
|
||||
$collection5['body']['$id'] => [
|
||||
'$id' => $collection5['body']['$id'],
|
||||
'Rating' => '10'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals($parentDocument['body'], $response['body']);
|
||||
|
||||
// Giving update permission of collection 3 to user.
|
||||
$this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::custom('collection3'),
|
||||
'name' => ID::custom('collection3'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::update(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
// This is the point of this test. We should be allowed to do this action, and it should not fail on permission check
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => ID::custom($collection2['body']['$id']),
|
||||
'Rating' => '10',
|
||||
$collection3['body']['$id'] => [
|
||||
'$id' => ID::custom($collection3['body']['$id']),
|
||||
'Rating' => '11',
|
||||
$collection4['body']['$id'] => [
|
||||
'$id' => ID::custom($collection4['body']['$id']),
|
||||
'Rating' => '10',
|
||||
$collection5['body']['$id'] => [
|
||||
'$id' => ID::custom($collection5['body']['$id']),
|
||||
'Rating' => '11'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(11, $response['body'][$collection2['body']['$id']]['collection3']['Rating']);
|
||||
|
||||
// We should not be allowed to update the document as we do not have permission for collection 2.
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => ID::custom($collection2['body']['$id']),
|
||||
'Rating' => '11',
|
||||
$collection3['body']['$id'] => null,
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// We should not be allowed to update the document as we do not have permission for collection 2.
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/documents/' . $collection2['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'Rating' => '11',
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// Removing update permission from collection 3.
|
||||
$this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection3', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::custom('collection3'),
|
||||
'name' => ID::custom('collection3'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
// Giving update permission to collection 2.
|
||||
$this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/collection2', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::custom('collection2'),
|
||||
'name' => ID::custom('collection2'),
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($userId)),
|
||||
Permission::update(Role::user($userId)),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
]
|
||||
]);
|
||||
|
||||
// Creating collection 3 new document
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection3['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => ID::custom('collection3Doc1'),
|
||||
'data' => [
|
||||
'Rating' => '20'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
// We should be allowed to link a new document from collection 3 to collection 2.
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => ID::custom($collection2['body']['$id']),
|
||||
$collection3['body']['$id'] => 'collection3Doc1',
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
|
||||
// We should be allowed to link and create a new document from collection 3 to collection 2.
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents/' . $collection1['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'Title' => 'Captain America',
|
||||
$collection2['body']['$id'] => [
|
||||
'$id' => ID::custom($collection2['body']['$id']),
|
||||
$collection3['body']['$id'] => [
|
||||
'$id' => ID::custom('collection3Doc2')
|
||||
],
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue