diff --git a/composer.lock b/composer.lock index 9b3091a80c..c2c48193bf 100644 --- a/composer.lock +++ b/composer.lock @@ -2056,12 +2056,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "b703f87e8190d362d93b64ac20992fc4988eb36a" + "reference": "44dda6914c7be148eb59ce11847386ce39f7b106" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/b703f87e8190d362d93b64ac20992fc4988eb36a", - "reference": "b703f87e8190d362d93b64ac20992fc4988eb36a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/44dda6914c7be148eb59ce11847386ce39f7b106", + "reference": "44dda6914c7be148eb59ce11847386ce39f7b106", "shasum": "" }, "require": { @@ -2112,7 +2112,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/refactor-permissions" }, - "time": "2022-08-23T01:36:40+00:00" + "time": "2022-08-24T10:22:04+00:00" }, { "name": "utopia-php/domains", diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 4df1c71760..7121af114a 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -48,13 +48,13 @@ trait DatabasesBase ]), [ 'collectionId' => ID::unique(), 'name' => 'Movies', + 'documentSecurity' => true, 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, ]); $this->assertEquals(201, $movies['headers']['status-code']); @@ -101,18 +101,20 @@ trait DatabasesBase ], ]); + $this->assertEquals(404, $responseCreateDocument['headers']['status-code']); + $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); + $this->assertEquals(404, $responseListDocument['headers']['status-code']); + $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/someID', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(404, $responseCreateDocument['headers']['status-code']); - $this->assertEquals(404, $responseListDocument['headers']['status-code']); $this->assertEquals(404, $responseGetDocument['headers']['status-code']); } @@ -2222,7 +2224,7 @@ trait DatabasesBase $this->assertEquals([], $document['body']['$permissions']); } - // Updated and Inherit Permissions + // Updated Permissions $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', @@ -2234,7 +2236,8 @@ trait DatabasesBase 'actors' => [], ], 'permissions' => [ - Permission::read(Role::any()), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])) ], ]); @@ -2245,8 +2248,11 @@ trait DatabasesBase // This differs from the old permissions model because we don't inherit // existing document permissions on update, unless none were supplied, // so that specific types can be removed if wanted. - $this->assertCount(1, $document['body']['$permissions']); - $this->assertContains(Permission::read(Role::any()), $document['body']['$permissions']); + $this->assertCount(2, $document['body']['$permissions']); + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + ], $document['body']['$permissions']); $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', @@ -2257,11 +2263,11 @@ trait DatabasesBase $this->assertEquals($document['body']['title'], 'Captain America 2'); $this->assertEquals($document['body']['releaseYear'], 1945); - // This differs from the old permissions model because we don't inherit - // existing document permissions on update, unless none were supplied, - // so that specific types can be removed if wanted. - $this->assertCount(1, $document['body']['$permissions']); - $this->assertContains(Permission::read(Role::any()), $document['body']['$permissions']); + $this->assertCount(2, $document['body']['$permissions']); + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + ], $document['body']['$permissions']); // Reset Permissions @@ -2283,10 +2289,18 @@ trait DatabasesBase $this->assertCount(0, $document['body']['$permissions']); $this->assertEquals([], $document['body']['$permissions']); + // Check user can still read document due to collection permissions of read("any") + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $document['headers']['status-code']); + return $data; } - public function testEnforceDocumentPermissions(): void + public function testEnforceCollectionAndDocumentPermissions(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -2294,10 +2308,10 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'EnforceCollectionPermissions', + 'name' => 'EnforceCollectionAndDocumentPermissions', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('EnforceCollectionPermissions', $database['body']['name']); + $this->assertEquals('EnforceCollectionAndDocumentPermissions', $database['body']['name']); $databaseId = $database['body']['$id']; $user = $this->getUser()['$id']; @@ -2307,7 +2321,7 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'collectionId' => ID::unique(), - 'name' => 'enforceCollectionPermissions', + 'name' => 'enforceCollectionAndDocumentPermissions', 'documentSecurity' => true, 'permissions' => [ Permission::read(Role::user($user)), @@ -2318,7 +2332,7 @@ trait DatabasesBase ]); $this->assertEquals(201, $collection['headers']['status-code']); - $this->assertEquals($collection['body']['name'], 'enforceCollectionPermissions'); + $this->assertEquals($collection['body']['name'], 'enforceCollectionAndDocumentPermissions'); $this->assertEquals($collection['body']['documentSecurity'], true); $collectionId = $collection['body']['$id']; @@ -2412,22 +2426,16 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - switch ($this->getSide()) { - case 'client': - $this->assertEquals(2, $documentsUser1['body']['total']); - $this->assertCount(2, $documentsUser1['body']['documents']); - break; - case 'server': - $this->assertEquals(3, $documentsUser1['body']['total']); - $this->assertCount(3, $documentsUser1['body']['documents']); - break; - } + // Current user has read permission on the collection so can get any document + $this->assertEquals(3, $documentsUser1['body']['total']); + $this->assertCount(3, $documentsUser1['body']['documents']); $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); + // Current user has read permission on the collection so can get any document $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); $email = uniqid() . 'user@localhost.test'; @@ -2460,6 +2468,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); + // Current user has no collection permissions but has read permission for this document $this->assertEquals(200, $document3GetWithDocumentRead['headers']['status-code']); $document2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document2['body']['$id'], [ @@ -2469,7 +2478,8 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - $this->assertEquals(401, $document2GetFailure['headers']['status-code']); + // Current user has no collection or document permissions for this document + $this->assertEquals(404, $document2GetFailure['headers']['status-code']); $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'origin' => 'http://localhost', @@ -2478,6 +2488,210 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); + // Current user has no collection permissions but has read permission for one document + $this->assertEquals(1, $documentsUser2['body']['total']); + $this->assertCount(1, $documentsUser2['body']['documents']); + } + + public function testEnforceCollectionPermissions() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'EnforceCollectionPermissions', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('EnforceCollectionPermissions', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $user = $this->getUser()['$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' => 'enforceCollectionPermissions', + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::create(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals($collection['body']['name'], 'enforceCollectionPermissions'); + $this->assertEquals($collection['body']['documentSecurity'], false); + + $collectionId = $collection['body']['$id']; + + sleep(2); + + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute', + 'size' => 64, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code'], 202); + $this->assertEquals('attribute', $attribute['body']['key']); + + // wait for db to add attribute + sleep(2); + + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'key_attribute', + 'type' => 'key', + 'attributes' => [$attribute['body']['key']], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals('key_attribute', $index['body']['key']); + + // wait for db to add attribute + sleep(2); + + $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $document1['headers']['status-code']); + + $document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $document2['headers']['status-code']); + + $document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'documentId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom('other2'))), + Permission::update(Role::user(ID::custom('other2'))), + ], + ]); + + $this->assertEquals(201, $document3['headers']['status-code']); + + $documentsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(3, $documentsUser1['body']['total']); + $this->assertCount(3, $documentsUser1['body']['documents']); + + $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(200, $document3GetWithCollectionRead['headers']['status-code']); + + $email = uniqid() . 'user2@localhost.test'; + $password = 'password'; + $name = 'User Name'; + $this->client->call(Client::METHOD_POST, '/account', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'userId' => ID::custom('other2'), + 'email' => $email, + 'password' => $password, + 'name' => $name, + ]); + $session2 = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $email, + 'password' => $password, + ]); + $session2 = $this->client->parseCookie((string)$session2['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + + $document3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions and document permissions are disabled + $this->assertEquals(401, $document3GetWithDocumentRead['headers']['status-code']); + + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions and document permissions are disabled + $this->assertEquals(401, $documentsUser2['headers']['status-code']); + + + // Enable document permissions + $collection = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'name' => $collection['body']['name'], + 'documentSecurity' => true, + ]); + + $documentsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions read access to one document $this->assertEquals(1, $documentsUser2['body']['total']); $this->assertCount(1, $documentsUser2['body']['documents']); } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index 3a079c6d22..8d4a19bd30 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -9,6 +9,7 @@ use Tests\E2E\Scopes\SideClient; use Utopia\Database\ID; use Utopia\Database\Permission; use Utopia\Database\Role; +use Utopia\Database\Validator\Authorization; class DatabasesPermissionsGuestTest extends Scope { @@ -88,19 +89,19 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - foreach ($documents['body']['documents'] as $document) { - foreach ($document['$permissions'] as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != 'read') { - continue; - } - $this->assertEquals($permission->getRole(), Role::any()->toString()); - } + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals($permissions, $documents['body']['documents'][0]['$permissions']); + + foreach ($roles as $role) { + Authorization::setRole($role); } } } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 29042178ce..aedc53854a 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -3,8 +3,8 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\ID; use Utopia\Database\Permission; @@ -29,16 +29,72 @@ class DatabasesPermissionsMemberTest extends Scope public function permissionsProvider(): array { return [ - [[Permission::read(Role::any())]], - [[Permission::read(Role::users())]], - [[Permission::read(Role::user(ID::custom('random')))]], - [[Permission::read(Role::user(ID::custom('lorem'))), Permission::update(Role::user('lorem')), Permission::delete(Role::user('lorem'))]], - [[Permission::read(Role::user(ID::custom('dolor'))), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))]], - [[Permission::read(Role::user(ID::custom('dolor'))), Permission::read(Role::user('lorem')), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))]], - [[Permission::update(Role::any()), Permission::delete(Role::any())]], - [[Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any())]], - [[Permission::read(Role::users()), Permission::update(Role::users()), Permission::delete(Role::users())]], - [[Permission::read(Role::any()), Permission::update(Role::users()), Permission::delete(Role::users())]], + [ + 'permissions' => [Permission::read(Role::any())], + 'any' => 1, + 'users' => 1, + 'doconly' => 1, + ], + [ + 'permissions' => [Permission::read(Role::users())], + 'any' => 2, + 'users' => 2, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('random')))], + 'any' => 3, + 'users' => 3, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('lorem'))), Permission::update(Role::user('lorem')), Permission::delete(Role::user('lorem'))], + 'any' => 4, + 'users' => 4, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('dolor'))), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))], + 'any' => 5, + 'users' => 5, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('dolor'))), Permission::read(Role::user('lorem')), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))], + 'any' => 6, + 'users' => 6, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::update(Role::any()), Permission::delete(Role::any())], + 'any' => 7, + 'users' => 7, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any())], + 'any' => 8, + 'users' => 8, + 'doconly' => 3, + ], + [ + 'permissions' => [Permission::read(Role::any()), Permission::update(Role::users()), Permission::delete(Role::users())], + 'any' => 9, + 'users' => 9, + 'doconly' => 4, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('user1')))], + 'any' => 10, + 'users' => 10, + 'doconly' => 5, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('user1'))), Permission::read(Role::user(ID::custom('user1')))], + 'any' => 11, + 'users' => 11, + 'doconly' => 6, + ], ]; } @@ -74,7 +130,6 @@ class DatabasesPermissionsMemberTest extends Scope 'documentSecurity' => true, ]); $this->assertEquals(201, $public['headers']['status-code']); - $this->collections = ['public' => $public['body']['$id']]; $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['public'] . '/attributes/string', $this->getServerHeader(), [ @@ -96,10 +151,25 @@ class DatabasesPermissionsMemberTest extends Scope 'documentSecurity' => true, ]); $this->assertEquals(201, $private['headers']['status-code']); - $this->collections['private'] = $private['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['private'] . '/attributes/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['private'] . '/attributes/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + $this->assertEquals(202, $response['headers']['status-code']); + + $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ + 'collectionId' => ID::unique(), + 'name' => 'Document Only Movies', + 'permissions' => [], + 'documentSecurity' => true, + ]); + $this->assertEquals(201, $private['headers']['status-code']); + $this->collections['doconly'] = $doconly['body']['$id']; + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $this->collections['doconly'] . '/attributes/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -118,9 +188,9 @@ class DatabasesPermissionsMemberTest extends Scope /** * Data provider params are passed before test dependencies * @dataProvider permissionsProvider - * @depends testSetupDatabase + * @depends testSetupDatabase */ - public function testReadDocuments($permissions, $data) + public function testReadDocuments($permissions, $anyCount, $usersCount, $docOnlyCount, $data) { $users = $data['users']; $collections = $data['collections']; @@ -144,66 +214,52 @@ class DatabasesPermissionsMemberTest extends Scope ]); $this->assertEquals(201, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', $this->getServerHeader(), [ + 'documentId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions + ]); + $this->assertEquals(201, $response['headers']['status-code']); + /** - * Check "any" collection + * Check "any" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], ]); - foreach ($documents['body']['documents'] as $document) { - $hasPermissions = \array_reduce([ - Role::any()->toString(), - Role::users()->toString(), - Role::user($users['user1']['$id'])->toString(), - ], function (bool $carry, string $role) use ($document) { - if ($carry) { - return true; - } - foreach ($document['$permissions'] as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() == 'read' && $permission->getRole() == $role) { - return true; - } - } - return false; - }, false); - - $this->assertTrue($hasPermissions); - } + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals($anyCount, $documents['body']['total']); /** - * Check role:member collection + * Check "users" permission collection */ - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', [ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], ]); - foreach ($documents['body']['documents'] as $document) { - $hasPermissions = \array_reduce([ - Role::any()->toString(), - Role::users()->toString(), - Role::user($users['user1']['$id'])->toString(), - ], function (bool $carry, string $role) use ($document) { - if ($carry) { - return true; - } - foreach ($document['$permissions'] as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() == 'read' && $permission->getRole() == $role) { - return true; - } - } - return false; - }, false); + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals($usersCount, $documents['body']['total']); - $this->assertTrue($hasPermissions); - } + /** + * Check "user:user1" document only permission collection + */ + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals($docOnlyCount, $documents['body']['total']); } }